??xml version="1.0" encoding="utf-8" standalone="yes"?>
下面是我做这个题之前别h的提C,有几个关键字Q?br>2^n个状?n为列敎ͼ我们做到按行更新Q更C行的时候我们按列来Q如果更新到最后一列,则换下一行?br>更新当前行时和上一行有兟?br>
q两句话l了开始的模糊印象。。但是确实有Ҏ?br>
下面?a title="cpg2001
" >cpg2001
用横U来划分阶段Q对于图一Q虽然划分后很整齐,但把某些砖分成了两半Q于是将他们也添加进来,于是变成了图二,其显得参差不齐,但最多也是向下突Z|在图三中Q我们将图二的空隙填满,则又转移C下一U状态?/span>
定义ȝ块状态ؓ1,否则?/span>0,则每行状态可以映到一个数(0,2^h})于是可徏立这L状?/span>a[ i Q?/span>j]Q表C第i行填满,W?/span>i+1行对应状态ؓj时的不同Ҏ敎ͼa[I,j]=?span>a[i-1,k]Q其中,状?span>k可导出状?span>j,初始化条?span>a[0,0]=1Q最?span>a[w,0]即ؓ所求?/span>
的启发,再加上zp的讲解逐渐清晰hQ?br>行数我们默认是从0开?/p>

W三行的赋值情?Q?00011
W四行的赋值情?Q?00100
W五行的赋值情?Q?11000
图一Q第三行填满了,W三行的W一个格子是一个竖形格子,q个竖Ş格子的上格子在第三行Q下格子在第四行Q于是在W四行需要补格子故置?Q第三行的第二个W三个格子是个横条,我们都置?Q紧接着又是一个竖形格子的上半个格子,同样?Q下面两个都是竖形格子的下半个置?
同理分别对W四行第五行赋?br>比如图二的第四行Q第二第三个两个q箋的零Q还有一U方案是摆一个横条?br>其他的详见注释?br>
我的代码Q?br>
#include<iostream>
#define max(a,b) (a>b?a:b)
int N,M,maxl=0;
__int64 ans[3000],tmp[3000];
void solve(int j,int last,int now)
{
if(j>M)
{
tmp[now]+=ans[last];
maxl=max(maxl,now);
return;
}
int up=(1<<(M-j))&last,uprt;
//up-->头顶上的那个格子状态,uprt-->头顶上的双的那个格子的状?br>
if(j==M)
{
if(!up)solve(j+1,last,now*2+1);//剩一个空了,q且上面的那个是0Q那么显然是竖条
//q一行需要补一个小Ҏ
//如果上面?Q显然下面仍然是要接着一个竖条,但是q个方格是上面q半个,无需|?
else solve(j+1,last,now*2);
}
else
{
uprt=(1<<(M-j-1))&last;
if(!up)
{
solve(j+1,last,now*2+1);
if(!uprt)//如果头顶上的不ؓ0Q头上双的也不ؓ0Q下面的可以放一个横?br>
solve(j+2,last,now*4);
}
else//q个地方时很Ҏ出错的,我这里认为是Wj列置?
//可以理解为是一个竖形条状的上半个格子,也可以认为是一个横行条状的左半个格?br>
//q里千万不能把这两种情况分开计算Q这样会重复?br>
solve(j+1,last,now*2);
}
}

int main()
{
int i,j;
while(scanf("%d%d",&N,&M)&&N)
{
if((N*M)%2)
{
printf("0\n");
continue;
}
memset(ans,0,sizeof(ans));
ans[0]=1;
for(i=1;i<=N;i++)
{
memset(tmp,0,sizeof(tmp));
for(j=0;j<=maxl;j++)
if(ans[j])solve(1,j,0);
memcpy(ans,tmp,sizeof(tmp));
}
printf("%I64d\n",ans[0]);
}
return 0;
}
37 37 22 7
0 15 15 6
0 0 9 5
0 0 4 4
0 0 0 3
0 0 0 2
0 0 0 1
#include<iostream>
#include<algorithm>
using namespace std;
#define Max 35
__int64 num[Max],dice[Max];
bool cmp(__int64 a,__int64 b)
{
return a<b;
}
void solve(int n)
{
__int64 i,j;
for(i=1;i<=dice[n];i++)
num[i]=1;
for(i=n;i>=1;i--)
for(j=dice[i]-1;j>=0;j--)
num[j]+=num[j+1];
}
int main()
{
int n,i;
while(scanf("%d",&n)!=EOF&&n){
memset(dice,0,sizeof(dice));
memset(num,0,sizeof(num));
for(i=1;i<=n;i++)
scanf("%I64d",&dice[i]);
sort(dice+1,dice+n+1,cmp);
solve(n);
printf("%I64d\n",num[1]);
}
return 0;
}