题目:http://acm.hdu.edu.cn/showproblem.php?pid=1693
第一道插头 DP !
直接用二进制数表示状态即可。
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=15,M=(1<<12)+5; int n,m,bin[N];ll dp[N][N][M]; int b[N][N]; void solve() { int lm=m+1; bin[0]=1;for(int i=1;i<=lm;i++)bin[i]=bin[i-1]<<1; memset(dp,0,sizeof dp); dp[1][1][0]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) for(int s=0;s<bin[lm];s++) { if(!dp[i][j][s])continue; ll tp=dp[i][j][s];bool d0=s&bin[j-1],d1=s&bin[j]; // ll tp not int tp!!!!! if(!b[i][j]) { if(!d0&&!d1)dp[i][j+1][s]+=tp; continue; } int t=s^bin[j-1]^bin[j]; if((d0&&d1)||(!d0&&!d1)) dp[i][j+1][t]+=tp; if((d0&&!d1)||(!d0&&d1)) dp[i][j+1][s]+=tp, dp[i][j+1][t]+=tp; } for(int s=0;s<bin[lm];s++) { if(!dp[i][lm][s]||s&bin[m])continue; dp[i+1][1][s<<1]+=dp[i][lm][s]; } } } int main() { int T; scanf("%d",&T); for(int t=1;t<=T;t++) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&b[i][j]); solve(); printf("Case %d: There are %lld ways to eat the trees. ", t,dp[n][m+1][0]); } return 0; }