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\n", 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\n", p[ans[i]].name);

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)