【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]); }