【cqbzoj】1785:残缺棋盘上放车的方案数 --状压dp --输入毁一生

博客介绍了如何解决在有限制的棋盘上放置车的问题,使得车彼此不相互攻击。通过使用状态转移动态规划(状压DP)的方法,确定在每行哪些列放置棋子的方案数。文章中提到,由于数据范围导致可能的答案超过int类型,因此使用long long。作者分享了遇到的输入问题,并表示在排查错误后会更新博客。
摘要由CSDN通过智能技术生成

【高级算法】残缺棋盘上放车的方案数

  时间限制:  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]);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值