状压dp 混乱的奶牛(有点裸)

链接:奶牛
混乱的奶牛 [Don Piele, 2007] Farmer John的N(4 <= N <= 16)头奶牛中的每一头都有一个唯一的编号S_i (1 <= S_i <= 25,000). 奶牛为她们的编号感到骄傲, 所以每一头奶牛都把她的编号刻在一个金牌上, 并且把金牌挂在她们宽大的脖子上. 奶牛们对在挤奶的时候被排成一支”混乱”的队伍非常反感. 如果一个队伍里任意两头相邻的奶牛的编号相差超过K (1 <= K <= 3400), 它就被称为是混乱的. 比如说,当N = 6, K = 1时, 1, 3, 5, 2, 6, 4 就是一支”混乱”的队伍, 但是 1, 3, 6, 5, 2, 4 不是(因为5和6只相差1). 那么, 有多少种能够使奶牛排成”混乱”的队伍的方案呢?

其实这个有点类似于TSP的思路,都是通过枚举当前和上一次的点来进行递推。

(话说这个题的状压也许并不是那么好想?)

思路:数据范围不大,应该说是异常的小,一般这种东西就应该往类似状压或者暴力的方向上去想了。

dp[i][j]:状态为j且队尾为i的情况下可行的方案数 ;

下一步考虑初始化:很明显应该在只放一头牛的情况下进行初始化,对于任意一头牛,它第一个放进去的时候,它就是队尾,并且此时可行数也只有1(毕竟只能放一头);

for(int i=1;i<=n;++i) dp[i][1<<(i-1)]=1; //初始化 

然后枚举所有状态,在所有可能的状态中,先任选一个已经被标为1(也就是已经在队伍里的牛)作为队尾,找到队尾后,再在标记为0(也就是还没进队)的牛中选一个插进来,如果这两头牛的编号满足要求(差的绝对值大于要求),这就是一个可行的方案了。

最后的状态一定是全为1的情况,那么把每头牛作为队尾的情况对应的方法数加起来就是了。

(如果想到状压的话还是比较裸的)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,s;
ll mas[20];
ll dp[20][(1<<18)+10];//状态为j且队尾为i的情况下可行的方案数 
int main()
{
	cin>>n>>s;
	for(int i=1;i<=n;++i) cin>>mas[i];
	for(int i=1;i<=n;++i) dp[i][1<<(i-1)]=1; //初始化 
    for(ll i=0;i<(1<<n);++i){
    	for(int j=1;j<=n;++j){
    		if(i&(1<<(j-1))){
    			for(int k=1;k<=n;++k){
    				if((i&(1<<(k-1)))) continue;
					if(abs(mas[j]-mas[k])<=s) continue;
					dp[k][i+(1<<(k-1))]+=dp[j][i];
				}
			}
		}
	}
	ll ans=0;
	for(int i=1;i<=n;++i){
	ans+=dp[i][(1<<n)-1];	
	}
	cout<<ans<<endl;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值