[USACO08NOV]奶牛混合起来Mixed Up Cows

 洛谷题目链接


状压$dp$:

本蒟蒻被动规虐的死去活来,于是决定死磕$dp$了!以前看到$dp$立刻走人。。

这篇文章可能对新手不太友好,二进制这种我就不讲了,主要是为了方便自己记忆(对不起$qwq$)


 进入正题:

首先,如何判断某些题目是不是状压$dp$呢,要看$n$的取值范围,当较小的时候,就可以考虑状压了。

那么我们设$f[j][i]$表示以第$j$头牛结尾,也就是最后一次加入队列的是第$j$头牛,并且现在队列状态为$i$的时候的方案数。

那么我们考虑现在要加入第$k$头奶牛,那么我们需要考虑一下几种情况:

$1、$第$j$头奶牛与新加的第$k$头奶牛相差不超过题目要求的时候,要排除

$2、$状态中第$j$头奶牛这个位置要为$1$,因为$j$既然是最后加入的,那肯定在队列中

$3、$状态中第$k$头奶牛这个位置要为$0$,因为你要加入他。

代码如下:

#include<iostream>
#include<cstdio>
#include<cmath>
#define int long long
#define N 20
using namespace std;
int n,m;
int val[N],f[N][1<<N];
signed main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%lld",&val[i]);
	for(int i=1;i<=n;++i)
		f[i][1<<(i-1)]=1;
	for(int i=1;i<(1<<n);++i)
		for(int j=1;j<=n;++j)
			for(int k=1;k<=n;++k)
			{
				if(((1<<(j-1))&i)==0||((1<<(k-1))&i)||abs(val[k]-val[j])<=m)
					continue;
				f[k][i+(1<<(k-1))]+=f[j][i];
			}
	int ans=0;
	for(int i=1;i<=n;++i)
		ans+=f[i][(1<<n)-1];
	printf("%lld",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/yexinqwq/p/10175974.html