题目链接:http://poj.org/problem?id=2411
题目思路:状态压缩dp,貌似如果有多次询问相同,可以记录答案。。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<queue> #include<algorithm> #include<vector> #include<stack> #include<list> #include<iostream> #include<map> using namespace std; #define inf 0x3f3f3f3f #define Max 110 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int n,m; int i; __int64 dp[12][1<<11]; int v[1<<11][1<<10]; int num[1<<11]; void dfs(int pos,int ps,int s) { if(pos==m) { v[ps][num[ps]++]=s; return; } if(pos+2<=m&&(s&(1<<(pos+1)))==0&&(s&(1<<pos))==0) dfs(pos+2,ps,s|(1<<(pos))|(1<<(pos+1))); dfs(pos+1,ps,s); } int main() { int j,k; while(scanf("%d%d",&n,&m),n|m) { memset(num,0,sizeof(num)); for(j=0;j<(1<<m);j++) { dfs(0,j,~j&((1<<m)-1)); //上面将上一行的零位补一,意思是必须放1*2的方块,一行的状态 //如果有零位表示这个位需要下面来补齐 } for(i=0;i<=n;i++) for(j=0;j<(1<<m);j++) dp[i][j]=0; dp[0][(1<<m)-1]=1; for(i=1;i<=n;i++) {
for(j=0;j<(1<<m);j++) { if(dp[i-1][j]==0) continue; for(k=0;k<num[j];k++) dp[i][v[j][k]]+=dp[i-1][j]; } } printf("%I64d\n",dp[n][(1<<m)-1]); } }