zoukankan      html  css  js  c++  java
  • hdu 1074 Doing Homework(状压DP)

    题意:

    有N(N<=15)个作业,每个作业有个名字、上交截止时间、完成它所耗的时间。

    一个作业每超期一天扣一分。

    问小余如何安排做作业的顺序,才能使扣的分最少。

    输出最少扣分,安排的顺序。

    思路:

    总共有N!个安排方案。暴力超时。所以想到用DP。

    如何表示状态?N小于等于15,可以用状态压缩。

    具体,,,,看代码吧,,

    这里用前一个状态推导后一个状态的方式,这样好写。 

    代码:

    struct node{
        char name[105];
        int deadline, days;
    }
    work[20];
    
    int n;
    int cn=0;
    int ds[36005];
    int dp[36005];
    int path[36005];
    
    
    
    void dfsCalc(int lastPos,int totalNum,int Num){ //正要打算从n个中选totalNum个,当前状态为Num
        if(totalNum<=0){
            ds[++cn]=Num;
            return;
        }
        rep(i,lastPos+1,n-totalNum+1){
            int NUM=Num+(1<<(i-1));
            dfsCalc(i,totalNum-1,NUM);
        }
    }
    
    int calcState(int state){
        int ans=0;
        rep(i,0,n-1){
            int t=(state&(1<<i));
            if(t!=0){
                ans+=(work[i+1].days);
            }
        }
        return ans;
    }
    
    
    bool cmp(node a,node b){
        return strcmp(a.name,b.name)<0;
    }
    
    int main(){
    
        int T;
        cin>>T;
        while(T--){
            scanf("%d",&n);
            rep(i,1,n){
                scanf("%s%d%d",work[i].name,&work[i].deadline,&work[i].days);
            }
    
            sort(work+1,work+1+n,cmp);
    
            mem(dp,inf);
    
            rep(i,1,n){
                int state=(1<<(i-1));
                if(work[i].days>work[i].deadline){
                    dp[state]=work[i].days-work[i].deadline;
                    path[state]=i;
                }else{
                    dp[state]=0;
                    path[state]=i;
                }
            }
            rep(i,1,n-1){
                cn=0;
                dfsCalc(0,i,0);
                rep(j,1,cn){
                    int oldState=ds[j];
                    rep(k,1,n){
                        if((oldState&(1<<(k-1)))==0){
                            int newState=oldState+(1<<(k-1));
                            int temp=calcState(oldState);
                            if(temp+work[k].days>work[k].deadline){
                                if( dp[oldState]+temp+work[k].days-work[k].deadline<dp[newState] ){
                                    dp[newState]=dp[oldState]+temp+work[k].days-work[k].deadline;
                                    path[newState]=k;
                                }
                            }else{
                                if( dp[oldState]<dp[newState] ){
                                    dp[newState]=dp[oldState];
                                    path[newState]=k;
                                }
                            }
                        }
                    }
                }
            }
    
            int N=(1<<n)-1;
            printf("%d
    ",dp[N]);
            int ansPath[15];
            int ansNum=0;
            while(N){
                    ansPath[++ansNum]=path[N];
                    N-=(1<<(path[N]-1));
            }
            rep2(i,ansNum,1){
                puts(work[ansPath[i]].name);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Android之打包签名
    on a null object reference 问题的解决办法
    Android Fragment使用小结及介绍
    Android开发重点难点:RelativeLayout(相对布局)详解
    Android的学习第六章(布局一LinearLayout)
    与adb相关的问题,比如掉线问题、Android Studio 提示Session 'app':Error Installing APK、找不到设备
    Android LitePal介绍与使用说明
    学习进度条-10
    《梦断代码》阅读笔记03
    用户模板和用户场景
  • 原文地址:https://www.cnblogs.com/fish7/p/4247968.html
Copyright © 2011-2022 走看看