bzoj1087: [SCOI2005]互不侵犯King

这道题我作为初学者来看有些懵。。
上网搜了一下发现大神都说是状态压缩。。
所以就开始学了一下状态压缩
状态压缩就是把每一行的状态转化为2进制,0表示不填,1表示填,只问合法状态,不用把每一个状态都问一遍。。
对时间和空间都很节省。。
这道题的dp方程也不难想(只要你会状压)。。
学会了状压之后很快就做出来了。。这道题还是比较入门。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<sstream>
using namespace std;
long long f[11][(1<<11)+10][90];     //f[i][j][k]表示第i行填j状态,填完之后前i行有k个king 
long long a[16][16],v[(1<<9)+10],vn;
long long t[610];
char s[110000];int n;
int main() {
    //freopen("king.in","r",stdin);freopen("king.out","w",stdout);
    for(int i=1;i<=600;i++) {  //t数组表示每一个状态有多少个1 
        int xx=i,m=0;
        while(xx!=0) {
            if(xx%2==1)
                m++;
            xx/=2;
        }
        t[i]=m;
    }
    int k;
    scanf("%d%d",&n,&k);
    memset(f,0,sizeof(f));
    int mmax=(1<<n)-1;
    for(int x=0;x<=mmax;x++) {   //存有用的状态 
        if(((x<<1)&x)==0) {
            f[1][x][t[x]]=1;
            v[++vn]=x;
        }
    }
    for(int i=2;i<=n+1;i++)
        for(int p=1;p<=vn;p++) {
            for(int q=1;q<=vn;q++) 
                if((v[p]&v[q])==0&&((v[p]>>1)&v[q])==0&&((v[p]<<1)&v[q])==0)   //状态是否合法 
                    for(int ii=k;ii>=t[v[p]];ii--)
                        f[i][v[p]][ii]=f[i][v[p]][ii]+f[i-1][v[q]][ii-t[v[p]]]; //dp方程 
        }
    printf("%lld\n",f[n+1][0][k]);          //n+1行不填表示了前n行所有的状态 
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值