【cqbzoj】1785:殘缺棋盤上放車的方案數 --狀壓dp --輸入毀一生

【高級算法】殘缺棋盤上放車的方案數

  時間限制: 1 Sec  內存限制: 64 MB

題目描述

  在 n*n(n≤20)的方格棋盤上放置 n 個車,某些格子不能放,求使它們不能互相攻擊的方案總數。

我們將每一行允許放棋子的位置設爲1,禁止的位置設爲0,例如1101表示該行上的第2列禁止放棋子。

輸入

第1行:1個整數n

接下來n行,每行n個0、1數字,表示第i行的允許禁止狀態

輸出

第1行:1個整數,表示放置方案的總數

樣例輸入

5
00111
01110
00110
01011
10011

樣例輸出

5


思路:就是狀壓DP

狀態表示目前到第i行已經在那幾列放了棋子時擺放的方案數

DP時考錄當行限制增加棋子累加即可(應該沒問題吧?應該是的。。。)

實現使用兩個數組互相交換指針

注意由於n=20,答案可能超出int範圍,所以用long long開數組



事實上我還沒有過掉這道題。。

寫了暴力dfs對拍了19000+組數據還是沒異常。。

等把錯誤弄清了再修改

希望有看出錯誤的大神指出錯誤!大笑



把這道題過了。。

原來是getchar的問題。。

再也不用getchar了。。。。

#include<cstdio>
#include<cstring>
#define ULL unsigned long long
#define MAXS (1<<20)
#define LL long long
ULL f1[MAXS],f2[MAXS];
int level[22];
char str[30];
int lowbit(int a)
{return a&-a;}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){//= =  就是這裏。。
        scanf("%s",str);
        for(int j=0;j<n;j++)
            level[i]<<=1,
            level[i]+=str[j]-'0';
    }
	
    ULL *p1=f1,*p2=f2,*tmp;
    int t1=level[1],t2,nn=(1<<n)-1;
    while(t1){
        t2=lowbit(t1);
        t1-=t2;
        p1[(~t2)&nn]=1;
    }
	
    for(int i=1;i<n;i++){
        memset(p2,0,sizeof f1);//sizeof f1==sizeof f2
        for(int j=1;j<=nn;j++)
            if(p1[j])for(int k=j,q=lowbit(j);k;k-=q,q=lowbit(k))
                    if((level[i+1]|q)==level[i+1])
                        p2[(~q)&j]+=p1[j];
        tmp=p1;
        p1=p2;
        p2=tmp;
    }
    printf("%llu",p1[0]);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章