hdu-6149 Valley Numer II 状压DP

http://acm.hdu.edu.cn/showproblem.php?pid=6149

把点分为low和high点,high点最多只有15个,所以可以用压位来处理其选取状态。

枚举low点,然后暴力枚举low点能连接的high点,记忆化搜索一下就好了

#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
const int N=35;
int n,m,k;
vector<int> g[N];
int bit[30];
bool h[N];
int has[N];
vector<int> low;
vector<int> hig;
int ans;
int dp[N][40000];
void dfs(int id,int d,int a)
{
    if(id==low.size())
    {
        ans=max(ans,a);
        return;
    }

    if(a<=dp[id][d])return;
    dp[id][d]=a;
    int li=low[id];
    for(int i=0; i<g[li].size(); i++)
    {
        int pi=g[li][i];
        if(!h[pi])continue;
        int hid1=has[pi];
        if(bit[hid1]&d)continue;
        for(int j=i+1; j<g[li].size(); j++)
        {
            int pj=g[li][j];
            if(!h[pj])continue;
            int hid2=has[pj];
            if(bit[hid2]&d)continue;
            dfs(id+1,d+bit[hid1]+bit[hid2],a+1);
        }
    }
    dfs(id+1,d,a);
}
int main()
{
    cin.sync_with_stdio(false);
    int t;
    bit[0]=1;
    for(int i=1; i<=15; i++)
        bit[i]=bit[i-1]*2;
    //cout<<bit[15]<<endl;32768
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>k;
        for(int i=0;i<n-k;i++)
            for(int j=0;j<(1<<k);j++)
                dp[i][j]=-1;
        for(int i=1; i<=n; i++)
            g[i].clear();
        low.clear();
        hig.clear();
        ans=0;
        fill(h,h+N,false);
        for(int i=0; i<m; i++)
        {
            int a,b;
            cin>>a>>b;
            g[a].push_back(b);
            g[b].push_back(a);
        }
        for(int i=0; i<k; i++)
        {
            int a;
            cin>>a;
            h[a]=true;
        }
        for(int i=1; i<=n; i++)
        {
            if(!h[i])
                has[i]=low.size(),low.push_back(i);
            else
                has[i]=hig.size(),hig.push_back(i);
        }
        for(int i=0;i<low.size();i++)
        {
            int lid=low[i];
            for(int j=g[lid].size()-1;j>=0;j--)
            {
                if(!h[g[lid][j]])
                    g[lid].erase(g[lid].begin()+j);
            }
        }
        dfs(0,0,0);
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/LukeStepByStep/p/8351805.html