hdu 1074 Doing Homework(状压dp)

题意:小明有n门课,每门课都给出了名字 截止时间 做完需要时间  如果到期没有做完,那么每天每门课要扣除一分,只有昨晚一门课才能去做另一门课

输出扣除分的最小值,并且输出序号字典序最小的那组做作业顺序

分析:只有15门课,可以想到用二进制表示每门课是否做完,那么接下来枚举每个状态就好了

输出方案的话,只要再开个数组记录pre就好了

#include<bits/stdc++.h>
using namespace std;
const int maxn=15;
int dp[1<<maxn],pre[1<<maxn],ttm[1<<maxn];
int b[maxn],c[maxn];
string a[maxn];

void print(int n){
    if(!n)return ;
    print(n-(1<<pre[n]));
    cout<<a[pre[n]]<<endl;
}

int main(){
    int n,t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=0;i<n;i++)cin>>a[i]>>b[i]>>c[i];
        int bit=1<<n;
        
        for(int i=1;i<bit;i++){
            dp[i]=INT_MAX;
            for(int j=n-1;j>=0;j--){
                if(!(i&(1<<j)))continue;
                
                int res=i-(1<<j);
                int cnt=ttm[res]+c[j]-b[j];
                if(cnt<0)cnt=0;
                if(cnt+dp[res]<dp[i]){
                    dp[i]=dp[res]+cnt;
                    ttm[i]=ttm[res]+c[j];
                    pre[i]=j;
                }
            }
        }
        
        cout<<dp[bit-1]<<endl;
        print(bit-1);
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/jihe/p/6554245.html