• HDU 1074


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

    状压dp,记录路径

    求最小值的状压dp非常裸,5分钟就写好了,记录路径有点麻烦,之前没怎么处理过这种问题

    我的方法是用一个map建立当前状态和前驱状态的映射,输出要按字典序,因为已经按字典序从大到小排好了,所以状态值比较小的优先(字典序小)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <map>
    using namespace std;
    
    const int INF = 0xfffffff;
    
    struct fuck{
        int w, pre;
    }dp[1<<15];
    
    struct node{
        char name[105];
        int D, C;
    }p[16];
    
    int cal(int x){
        int res = 0, cnt = 0;
        while(x){
            if(x & 1){
                res += p[cnt].C;
            }
            cnt++;
            x >>= 1;
        }
        return res;
    }
    
    int cnt(int x){
        int res = 0;
        while(x){
            if(x & 1){
                res++;
            }
            x >>= 1;
        }
        return res;
    }
    
    int cal1(int x, int y){
        int res = 0;
        while(1){
            if((x&1) != (y&1)){
                return res; 
            }
            res++; 
            x >>= 1; y >>= 1; 
        }
    }
    
    int ans[25], ct;
        
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            int n;
            scanf("%d", &n);
            for(int i = 0; i < (1<<n); i++)
                dp[i].w = INF;
            int xx = 0;
            while(1){
                dp[(1<<xx)].pre = 0; 
                xx++; 
                if(xx == n) break;
            }
            for(int i = 0;i < n; i++){
                scanf("%s %d %d", p[i].name, &p[i].D, &p[i].C);
                if(p[i].C > p[i].D)
                    dp[1<<i].w = p[i].C - p[i].D;
                else 
                    dp[1<<i].w = 0;
            }
            map <int, int> mp; 
            for(int i = 0; i < (1<<n); i++){
                for(int j = 0; j < n; j++){
                    if(i&(1<<j)){
                        if(cal(i) > p[j].D){
                            if(dp[i].w > dp[i^(1<<j)].w + cal(i) - p[j].D){
                                dp[i].w = dp[i^(1<<j)].w + cal(i) - p[j].D;
                                dp[i].pre = i^(1<<j); 
                                mp[i] = i^(1<<j);    
                            }
                            else if(dp[i].w == dp[i^(1<<j)].w + cal(i) - p[j].D && dp[i].pre > (i^(1<<j))){
                                dp[i].pre = i^(1<<j); 
                                mp[i] = i^(1<<j);      
                            }
                                //dp[i] = min(dp[i], dp[i^(1<<j)] + cal(i) - p[j].D);
                        }
                        else{
                            if(dp[i].w > dp[i^(1<<j)].w){
                                dp[i].w = dp[i^(1<<j)].w;
                                dp[i].pre = i^(1<<j);
                                mp[i] = i^(1<<j); 
                            }
                            else if(dp[i].w == dp[i^(1<<j)].w && dp[i].pre > (i^(1<<j))){
                                dp[i].pre = i^(1<<j);
                                mp[i] = i^(1<<j); 
                            }
                            //dp[i] = min(dp[i], dp[i^(1<<j)]);
                        }
                    }
                }
            }
            printf("%d
    ", dp[(1<<n)-1]);
            int now = (1<<n) - 1; 
            ct = 0; 
            while(now){
                ans[ct++] = cal1(now, mp[now]);
                now = mp[now]; 
            }
            for(int i = n - 1; i >= 0; i--){
                printf("%s
    ", p[ans[i]].name);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    背包问题_模板
    hihoCoder week14 无间道之并查集
    hihoCoder week13 最近公共祖先·一
    图片处理工具类 util
    算法导论 第二章 递归与分治
    hihoCoder week12 刷油漆
    hihoCoder week11 树中的最长路
    hihoCoder week10 后序遍历
    hihoCoder week8 状态压缩·一
    hihoCoder week7 完全背包
  • 原文地址:https://www.cnblogs.com/xiaohongmao/p/4055537.html
Copyright © 2020-2023  润新知