• hdu6149 Valley Numer II 分组背包+状态压缩


    /**
    题目:hdu6149 Valley Numer II
    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149
    题意:
    众所周知,度度熊非常喜欢图。
    为了形成山谷,首先要将一个图的顶点标记为高点或者低点。
    标记完成后如果一个顶点三元组<X, Y, Z>中,
    X和Y之间有边,Y与Z之间也有边,同时X和Z是高点,Y是低点,那么它们就构成一个valley。
    度度熊想知道一个无向图中最多可以构成多少个valley,一个顶点最多只能出现在一个valley中。
    ● 1≤T≤20
    ● 1≤N≤30
    ● 1≤M≤N*(N-1)/2
    ● 0≤K≤min(N,15)
    ● 1≤Xi, Yi≤N, Xi!=Yi
    ● 1≤Vi≤N
    思路:由于k最大是15,所以可以分组背包+状态压缩
    
    因为每两个高点和一个低点才能构成一个三元组,k最大15,所以最多7个三元组;
    
    所有的低点作为分组条件。
    每一组存入可以和该低点构成三元组的pair<x,z>,用s表示状态;
    
    dp[i][s]表示放入i体积,高点状态为s可以获得的最多三元组;
    
    dp[i][s] = max(dp[i][s],dp[i-1][s-s1]+1) (s&(s1)==0)
    
    ps:自己老是在这个地方搞错,dp[7][i]这里的第一维要开到8以上!!!
    
    
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <map>
    using namespace std;
    typedef long long LL;
    #define ms(x,y) memset(x,y,sizeof x)
    typedef pair<int, int> P;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const int N =10005;
    int dp[8][1<<15];
    vector<int> v[31];
    int f[33][33];
    int gao[33], pos[33];
    vector<int> g;
    int main()
    {
        int T;
        int n, m, k;
        cin>>T;
        while(T--)
        {
            scanf("%d%d%d",&n,&m,&k);
            ms(f,0);
            int x, y;
            for(int i = 1; i <= m; i++){
                scanf("%d%d",&x,&y);
                f[x][y] = 1;
                f[y][x] = 1;
            }
            ms(gao,0);
            g.clear();
            for(int i = 1; i <= k; i++){
                scanf("%d",&x);
                pos[x] = i-1;
                g.push_back(x);
                gao[x] = 1;
            }
            for(int i = 1; i<= n; i++) v[i].clear();
            for(int i = 1; i <= n; i++){
                if(gao[i]==0){
                    for(int j = 0; j<g.size();j++){
                        for(int z = j+1; z <g.size(); z++){
                            if(f[i][g[j]]&&f[i][g[z]]){
                                v[i].push_back((1<<pos[g[j]])|(1<<pos[g[z]]));
                            }
                        }
                    }
                }
            }
            memset(dp, -inf, sizeof dp);
            dp[0][0] = 0;
            int len = 1<<k;
            for(int i = 1; i <= n; i++){
                if(gao[i]||(int)v[i].size()==0) continue;
                for(int j = 7; j >= 1; j--){
                    for(int x = 0; x < v[i].size(); x++){
                        for(int y = 0; y < len; y++){
                            if((y&v[i][x])==v[i][x]){
                                dp[j][y] = max(dp[j][y],dp[j-1][y-v[i][x]]+1);
                            }
                        }
                    }
                }
            }
            int mas = 0;
            for(int i = 1; i <= 7; i++){
                for(int j = 0; j < len; j++){
                    mas = max(mas,dp[i][j]);
                }
            }
            printf("%d
    ",mas);
        }
        return 0;
    }
  • 相关阅读:
    腾讯课堂——基础数据类型(dict字典)
    腾讯课堂——基础数据类型(tuple元祖)
    基础数据类型(list列表)
    第 018讲:函数:灵活即强大(关键字函数,默认函数,收集函数)
    第 015讲:字符串:格式化
    第 013讲: 元组tuple 上了枷锁的列表
    第 012讲:打了激素的数组3
    第 011讲:一个打了激素的数组[02]
    range函数的用法
    第 010讲:一个打了激素的数组[01]
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7390995.html
Copyright © 2020-2023  润新知