P1879 [USACO06NOV]玉米田Corn Fields
看到 N 较小 , 应该能想到 状态压缩
F[I][J]
表示第I行处于状态J,总的方案数 ;
那么容易得出F[I][J] = F[i][j]=sum(F[i−1][0],F[i−1][1],F[i−1][2])F[i][j]=sum(F[i-1][0],F[i-1][1],F[i-1][2])F[i][j]=sum(F[i−1][0],F[i−1][1],F[i−1][2])
-
判断状态是否合法
(i<<1)&i
这可以判断I中是否有相邻的两个1;
-
调试的小技巧
显示数字代表的状态
string Dbg(int X) { string Ans = "" ; for (R int i = 0 ; i < M ; ++ i) { Ans = (char)('0' + (((1<<i)&X)?1:0)) + Ans ; } return Ans ; }
-
Code
#include <string.h> #include <stdio.h> #define re register #define gc getchar() int Qread () { int x = 0,f = 1; char ch = gc ; while (ch >'9' || ch < '0') { if (ch =='-')f = -1; ch = gc ; } while (ch >='0' && ch <='9') { x = x * 10 + ch -'0' ; ch = gc ; } return x *f ; } const int Wzx = 100000000 ; int N , M ,F[14][4098]; unsigned short int A[14] , Pw; int main () { //freopen ("P1879.in" , "r" , stdin) ; N = Qread () , M = Qread () ; Pw = 1 << M ; memset (A , 0 ,sizeof (A)) ; re unsigned int i , j , k; for (i = 0; i < N; ++ i) { for (j = 0 ; j < M ; ++ j) { A[i]= A[i] | (Qread() << j) ; } A[i] = ~A[i] ; } memset (F , 0 , sizeof (F)) ; for (i = 0 ; i < Pw ; ++ i) { if ((i >> 1) & i) continue ; if (i&A[0]) continue ; F[0][i] = 1 ; } for (i = 1; i < N ; ++ i) { for (j = 0 ; j < Pw; ++ j) { if ((j>>1) & j) continue ; if (j&A[i]) continue ; for (k = 0 ; k < Pw ; ++ k) { if (k&A[i-1]) continue ; if (k&j)continue ; F[i][j] += F[i-1][k] ; F[i][j] %= Wzx; } } } int Ans = 0 ; for (i = 0 ; i < Pw ; ++ i) { Ans += F[N-1][i] ; Ans %= Wzx; } printf ("%d\n" , Ans) ; fclose (stdin) ; fclose (stdout); return 0; }
Thanks!