hdu 1074

状态压缩题,要注意的是有多种情况扣分相同,那么要按照字典序输出,也就是输入时在前,那么输出也要在前。具体看代码注释。
参考文章:


#include <iostream>
#include <stdio.h>
#include <string>
#include <stack>
using namespace std;

const int maxn=1<<17;
struct homework{
    char name[150];
    int deadline;
    int timecost;//做作业所花费的时间
}h[30];
struct node{
    int score;//当前的扣分情况
    int time;//当前所花的天数
    int num;//当前所做作业的序号
    int pre;//上一个状态的地址
}dp[maxn];//数组要开的足够大,数字上限为2^n

int main(){
    int T,N;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        for(int i=0;i<N;i++)    scanf("%s%d%d",&h[i].name,&h[i].deadline,&h[i].timecost);
        dp[0].score=0;
        dp[0].time=0;
        int M=(1<<N)-1;
        for(int i=1;i<=M;i++){//用二进制的0~n-1位来表示作业1~n的完成情况,0为都没有完成,(1<<N)-1表示所有作业都完成,这里进行遍历
            dp[i].score=100000;//保证dp[i]得到初始化
            for(int j=N-1;j>=0;j--){//j从大到小每个作业遍历,保证字典序输出
                int temp=1<<j;
                if((i&temp)==temp){//表示当前作业状态是做了j号作业的
                    int k=i-temp;//表示上一个状态,也就是没有做j号作业,其余与这个状态一样
                    int x=dp[k].time+h[j].timecost-h[j].deadline;
                    if(x<0)
                        x=0;//计算做j号作业是否逾期,若没有预期逾期则不扣分
                    if(dp[k].score+x<dp[i].score){//若为扣分最少的情况,则更改信息
                        dp[i].score=dp[k].score+x;
                        dp[i].num=j;
                        dp[i].time=dp[k].time+h[j].timecost;
                        dp[i].pre=k;
                    }
                }
            }
        }
        printf("%d\n",dp[M].score);
        stack<int>st;
        while(M!=0){
            st.push(dp[M].num);
            M=dp[M].pre;
        }
        while(!st.empty()){
            printf("%s\n",h[st.top()].name);
            st.pop();
        }

    }
    return 0;
}

确实不是很懂这题,出错的地方请见谅。

猜你喜欢

转载自blog.51cto.com/13688928/2112632