2 1 *....... ....*... .......* .....*.. ..*..... ......*. .*...... ...*.... 2 *....... ....*... .......* .....*.. ..*..... ......*. .*...... ...*....
56 1409
额……简单的状态dp。
记录前两行推第三行,没什么说的。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; char map[10][10]; int dp[8][12][(1<<8)][(1<<8)]; int av[10][(1<<8)+5]; int up[10]; int cnt[(1<<8)+5]; int main() { int i,j,n,T,p,k,l,m; scanf("%d",&T); memset(cnt,0,sizeof(cnt)); for (i=0;i<(1<<8);i++) { for (j=0;j<8;j++) { if ((i & (1<<j))!=0) cnt[i]++; } } while(T--) { scanf("%d",&p); for (i=0;i<8;i++) { scanf("%s",map[i]); } memset(dp,0,sizeof(dp)); memset(av,0,sizeof(av)); memset(up,0,sizeof(up)); for (i=0;i<8;i++) { for (j=0;j<(1<<8);j++) { for (k=0;k<8;k++) { if (map[i][k]=='*' && (j & (1<<k))!=0) break; } if (k==8) av[i][up[i]++]=j; } } for (i=0;i<up[0];i++) { dp[0][cnt[av[0][i]]][0][av[0][i]]=1; } for (i=0;i<=p;i++) { for (j=0;j<up[0];j++) { if (dp[0][i][0][av[0][j]]==0) continue; for (k=0;k<up[1];k++) { if (i+cnt[av[1][k]]>p) continue; if (((av[0][j]<<2) & av[1][k])==0 && ((av[1][k]<<2) & av[0][j])==0) dp[1][i+cnt[av[1][k]]][av[0][j]][av[1][k]]+=dp[0][i][0][av[0][j]]; } } } for (i=2;i<8;i++) { for (j=0;j<=p;j++) { for (k=0;k<up[i];k++) { if (cnt[av[i][k]]+j>p) continue; for (l=0;l<up[i-2];l++) { if (((av[i][k]<<1) & av[i-2][l])!=0 || (av[i][k] & (av[i-2][l]<<1))!=0) continue; for (m=0;m<up[i-1];m++) { if (((av[i][k]<<2) & av[i-1][m])!=0 || ((av[i-1][m]<<2) & av[i][k])!=0) continue; dp[i][cnt[av[i][k]]+j][av[i-1][m]][av[i][k]]+=dp[i-1][j][av[i-2][l]][av[i-1][m]]; } } } } } int ans=0; for (i=0;i<up[6];i++) { for (j=0;j<up[7];j++) { ans+=dp[7][p][av[6][i]][av[7][j]]; } } printf("%d\n",ans); } return 0; }