洛谷P2915 Usaco08 Mixed Up Cows - 状态压缩

49 篇文章 0 订阅
6 篇文章 0 订阅

标准的状压题!

所谓状态压缩就是将状态用二进制存储下来,并用位运算实现转移
用二进制存储,可以不重不漏地遍历到所有的状态

我们设0表示牛已在队伍中,1表示牛不在队伍中,最后需要求得全部为1的状态
设状态为f(i,j)表示第i头牛在队尾,队伍状态为j(一个二进制数)时的方案数

答案为 n1f(i,(1111...1)2) ,这里 (1111...1)2 表示由n个1组成的二进制数

在讲到转移之前,有必要提一下位运算。将1左移N位,得到的二进制数其实是一个1后面带上N个0,这和我们需要的N个1不符

但是这个时候我们发现 1000021=(1111)2
而位运算的优先级又是很低的,所以代码里就需要写成i<=(1<<n)-1

转移过程则是先从小到大地枚举队伍状态i(一个二进制数),再不断地向队尾添加元素。
枚举队尾j,再枚举一个可以和队尾相接的元素p,就可以得到转移方程:
f[p][i|(1<<p-1)] += f[j][i]

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
int a[20],n,k;
long long f[20][1<<16],ans;
int main() {
    cin >> n >> k;
    for(int i=1; i<=n; i++) 
        cin >> a[i];
    for(int i=1; i<=n; i++) 
        f[i][1<<(i-1)] = 1; 
    for(int i=1; i<=(1<<n)-1; i++)
        for(int j=1; j<=n; j++)
            if(i&(1<<j-1))
                for(int p=1; p<=n; p++) 
                    if(!(i&(1<<p-1)) && abs(a[p]-a[j]) > k)  //转移 
                        f[p][i|(1<<p-1)] += f[j][i];
    for(int i=1; i<=n; i++) 
        ans += f[i][(1<<n)-1];
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值