HDU3091 (2n个分成n对使得结果最小 n小于等于10 状压dp 根据题目特性减少状态)

题目
HDU3091 (2n个分成n对使得结果最小 n小于等于10 状压dp 根据题目特性减少状态)_第1张图片
转自
HDU3091 (2n个分成n对使得结果最小 n小于等于10 状压dp 根据题目特性减少状态)_第2张图片

#include
typedef long long ll;
using namespace std;
const int N=19;
int ok[N][N],A[N],B[N];ll dp[1<<N][N];
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        memset(ok,0,sizeof ok),memset(dp,0,sizeof dp);dp[1][1]=1;
        for(int i=1,x,y;i<=m;++i) scanf("%d%d",&x,&y),ok[x][y]=ok[y][x]=1;
        int t=1<<n;
        for(int i=0;i<t;++i){
            int o1=0,o2=0;
            for(int j=1;j<=n;++j) (i&(1<<(j-1)))?(A[++o1]=j):B[++o2]=j;
            for(int x=1;x<=o1;++x)
                for(int y=1;y<=o2;++y) if(ok[A[x]][B[y]]) dp[i|(1<<(B[y]-1))][B[y]]+=dp[i][A[x]];
        }
        ll ans=0;
        for(int i=1;i<=n;++i) if(ok[1][i]) ans+=dp[t-1][i];
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:(DP==状压dp)