【高級算法】殘缺棋盤上放車的方案數
時間限制: 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]);
}