很久没有做题了,前天做了一道题结果弱的一逼。。。搜了解题报告不说...还尼玛秀了上限
题意:
给出宽和高为n和m的一堵墙,手上有长为1,2,3,4高均为1的砖,问形成一个坚固的墙有多少种做法。
坚固的意思是,不能一刀切到底。
解法:
将问题进行分解。求的所有坚固的墙ans(w,h)=所有墙all(w,h)-所有不坚固的墙bro(w,h)
所有的墙all(w,h)=一层的所有情况x(w)**h
所有不坚固的墙bro(w,h) = ans(1,h)*all(w-1,h)+ans(2,h)*all(w-2,h)+...+ans(w-1,h)*all(1,h)
x(w,1) = x(w-1,1)+x(w-2,1)+x(w-3,1)+x(w-4,1)
显然剩下的就是dp了
细节:
因为取余数,做减法的时候,有可能会发生不够减的情况记得+R就好
自己犯的错误:
这题的范围是t <=100 n,m<=1000
如果对于每个case都进行dp的话,是n*n*t的复杂度
然后如果进行预处理的话是n*n*n
然后问题就出在这里了 预处理的话会TLE
但是有个cheat的办法就是输入之后先判断下每个高度最大的w就能过。
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cstring> using namespace std; const int MAXSIZE = ;
const int R = ;
int wall[MAXSIZE][MAXSIZE];
int ans[MAXSIZE][MAXSIZE];
int vw[MAXSIZE];
int vh[MAXSIZE];
int hm[MAXSIZE];
int t;
int wmax;
int hmax; void input(){
cin>>t;
for ( int i = ; i < t; i++ ) {
cin>>vh[i]>>vw[i];
wmax = wmax<vw[i] ? vw[i]:wmax;
hmax = hmax>vh[i] ? hmax:vh[i];
}
for ( int i = ; i < t; i++ ) {
hm[vh[i]] = hm[vh[i]]>vw[i] ? hm[vh[i]]:vw[i];
}
} void init() {
memset(wall,,sizeof(wall));
memset(ans,,sizeof(ans));
wall[][] = ;
wall[][] = ;
wall[][] = ;
wall[][] = ;
ans[][] = ;
ans[][] = ;
ans[][] = ;
ans[][] = ;
for ( int w = ; w <= wmax; w++ ) {
wall[w][] = (wall[w][] + wall[w-][]%R)%R;
wall[w][] = (wall[w][] + wall[w-][]%R)%R;
wall[w][] = (wall[w][] + wall[w-][]%R)%R;
wall[w][] = (wall[w][] + wall[w-][]%R)%R;
}
for ( int h = ; h <= hmax; h++ ) {
wall[][h] = ;
ans[][h] = ;
}
for ( int w = ; w <= wmax; w++ ) {
for ( int h = ; h <= hmax; h++ ) {
wall[w][h] = ((long long)wall[w][h-]*wall[w][])%R;
}
}
for ( int h = ; h <= hmax; h++ ) {
for ( int w = ; w <= hm[h]; w++ ) {
long long t = ;
for ( int k = ; k < w; k++ ) {
t += (long long)ans[k][h]*wall[w-k][h];
t %= R;
}
ans[w][h] = wall[w][h] > t? wall[w][h]-t:wall[w][h]-t+R;
ans[w][h] %= R;
}
}
} void solve() {
for ( int i = ; i < t; i++ ) {
cout<<ans[vw[i]][vh[i]]<<endl;
}
} int main() {
input();
init();
solve();
return ;
}
sb一般的代码
最近老师安排的事情比较多,,,书看的也慢了。。。简直是弱爆了。。。