標籤:style blog http for ar art amp log
看了這位博主的經曆
http://blog.csdn.net/lenleaves/article/details/7972224
感覺有些差不多,因為CF比賽狀壓被虐 所以開始刷刷題,從最簡單的開始複習吧,細節處理很差,唉
DP方程跟一般的有些不一樣,dp[i][j]表示在狀態i的情況下 到第j行的擺放有多少種,然後總數就是 dp[i][n - 1]求和,以第一行為邊界往下推,第一行邊界值為1,因為從第一行開始目前狀態當然就一種擺法了,可是原圖本身就有些地方能放不能放的,一開始放在一起處理了很煩弄不清楚了,後來看了別人的,先處理掉原圖的合法不合法,看來我太年輕,這樣接下來就很清晰了,當然題目說 每一行都不放也是一種狀態,一開始給看漏了,結果一直案例跑錯,還以為推錯了,看方程看了半年
#define MOD 100000000int n,m,cnt;int mp[15];int aa[1<<15];int dp[1<<15][15];void init() {memset(mp,0,sizeof(mp));memset(dp,0,sizeof(dp));memset(aa,0,sizeof(aa));}bool input() {while(scanf("%d %d",&n,&m) == 2) {for(int i=0;i<n;i++)for(int j=0;j<m;j++){int x;scanf("%d",&x);if(x == 0)mp[i] |= (1<<(m - j - 1));//不能放的拎出來}return false;}return true;}bool isok1(int x) {if(x&(x<<1))return 0;//判相鄰兩列return 1;}bool isok2(int x,int i) {if(x&mp[i])return 0;return 1;}void cal() {cnt = 0;for(int i=0;i<(1<<m);i++) if(isok1(i))aa[cnt++] = i;//先把與原圖就衝突的給排掉留下合法的for(int i=0;i<cnt;i++)if(isok2(aa[i],0))dp[aa[i]][0] = 1;for(int i=1;i<n;i++) {for(int j=0;j<cnt;j++) {if(!isok2(aa[j],i))continue;for(int k=0;k<cnt;k++)//一開始這裡令j != k因為相鄰兩行狀態肯定不一樣,可是忽略了兩行都可以不放 if(isok2(aa[k],i - 1) && !(aa[k]&aa[j])/*判上下行是否合法*/)dp[aa[j]][i] = (dp[aa[j]][i] + dp[aa[k]][i - 1])%MOD;}}}void output() {int ans = 0;for(int i=0;i<cnt;i++)ans = (ans + dp[aa[i]][n - 1])%MOD;cout<<ans<<endl;}int main () {while(true) {init();if(input())return 0;cal();output();}}