hdu 6149 Valley Numer II(01背包套状压dp)

题目链接:hdu 6149 Valley Numer II

题意:

给你N个点,有k个为高点,其他为低点,现在这N个点有m条边,问你最多能组成多少个两个高点一个低点,低点和两个高点都有边相连这样的状态。

每个点只能出现在一个状态里面。

题解:

考虑将高点进行状态压缩一下。那么枚举每一个低点,看看能对那些状态有影响,那么就更新那些状态,相当于外层是个01背包,枚举物品,内层就是一个状压dp。

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 
 6 const int N=33;
 7 int T,n,m,K,x,y,now,dp[2][1<<15],h[N],mp[33][33],a[N];
 8 
 9 void gmax(int &a,int b){if(a<b)a=b;}
10 
11 int main(){
12     scanf("%d",&T);
13     while(T--)
14     {
15         scanf("%d%d%d",&n,&m,&K);
16         mst(dp,0),mst(h,0),mst(mp,0);
17         F(i,1,m)
18         {
19             scanf("%d%d",&x,&y);
20             mp[x][y]=mp[y][x]=1;
21         }
22         F(i,0,K-1)scanf("%d",a+i),h[a[i]]=1;
23         int U=(1<<K)-1;
24         now=0;
25         F(i,1,n)
26         {
27             if(h[i])continue;
28             now^=1;
29             memcpy(dp[now],dp[now^1],sizeof(dp[now]));
30             F(j,0,U)F(k,0,K-1)
31             {
32                 if((j&(1<<k))||!mp[i][a[k]])continue;
33                 F(t,k+1,K-1)
34                 {
35                     if((j&(1<<t))||!mp[i][a[t]])continue;
36                     gmax(dp[now][j|(1<<k)|(1<<t)],dp[now^1][j]+1);
37                 }
38             }
39         }
40         int ans=0;
41         F(i,0,U)gmax(ans,dp[now][i]);
42         printf("%d
",ans);
43     }
44     return 0;
45 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7401323.html