1. 程式人生 > >2018.10.27 洛谷P2915奶牛混合起來Mixed Up Cows(狀壓dp)

2018.10.27 洛谷P2915奶牛混合起來Mixed Up Cows(狀壓dp)

傳送門
狀壓dp入門題。
按照題意建一個圖。
要求的就是合法的鏈的總數。
直接 f [ i ] [ j ] f[i][j]

表示當前狀態為 j j ,下一位要跟 i i 連起來的方案數。
然後從沒被選並且跟 i
i
連通的點轉移就行了。
程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=20;
bool tran[N][N];
int n,K,up,s[N];
ll f[N][1<<16];
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(
ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } inline ll dfs(int pos,int sta){ if(~f[pos][sta])return f[pos][sta]; if(sta+1==up)return f[pos][sta]=1; f[pos][sta]=0; for(int i=1;i<=n;++i){ if(!tran[i][pos]||((sta>>(i-1))&1))continue; f[pos][sta]+=dfs(i,sta|(1<<(i-1))); } return f[pos][sta]; } int main(){ memset(f,-1,sizeof(f)),n=read(),K=read(),up=1<<n; for(int i=1;i<=n;++i){ s[i]=read(); for(int j=1;j<i;++j)if(abs(s[i]-s[j])>K)tran[i][j]=tran[j][i]=1; tran[i][0]=tran[0][i]=1; } cout<<dfs(0,0); return 0; }