Doing Homework HDU - 1074

有n个任务,每个任务有一个截止时间,超过截止时间一天,要扣一个分。
求如何安排任务,使得扣的分数最少。

Input

有多组测试数据。第一行一个整数表示测试数据的组数
第一行一个整数n(1<=n<=15) 
接下来n行,每行一个字符串(长度不超过100)表示任务的名称和两个整数,分别表示任务的截止时间和完成任务需要的天数。 这n个任务是按照字符串的字典序从小到大给出。

Output

每组测试数据,输出最少扣的分数的。 并输出一个完成任务的方案,如果有多个方案,输出字典序最小的一个。

Sample Input

2
3
Computer 3 3
English 20 1
Math 3 2
3
Computer 3 3
English 6 3
Math 6 3

Sample Output

2
Computer
Math
English
3
Computer
English
Math

思路:

1. dp[i]表示状态为i所扣的分,time[i]表示状态为i时最短用多长时间,last[i]记录状态i的最后一个任务编号,可以打印路径。

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

int del[20],cost[20],time[1<<16],dp[1<<16],n,last[1<<16];
string task[20];

void print(int mask){
    if(!mask) return;//mask=0全部任务输出完毕
    print(mask-(1<<last[mask])); //输出其前面的状态
    cout<<task[last[mask]]<<endl;//输出mask的最后一个任务
}
int main()
{
    int t;
    cin>>t;
    while(t--){
       cin>>n;
       for(int i=0; i<n; i++){
          cin>>task[i]>>del[i]>>cost[i];
       }
       memset(time,0,sizeof(time));
       for(int mask=1; mask<(1<<n); mask++){
         dp[mask]=0x7fffffff;
         for(int end=0; end<n; end++)//注意字典序小的优先输出,下面更新是有等于符号的。若是逆序,就少个等于号就行了
         {
             int k=1<<end;
             if(!(mask&k))continue;//这里假如写成if((mask&k)==0)mask&k一定要加括号
             int sc=time[mask-k]+cost[end]-del[end];
             sc=max(0,sc);
             if(dp[mask]>=dp[mask-k]+sc){//有等于
                dp[mask]=dp[mask-k]+sc;
                time[mask]=time[mask-k]+cost[end];
                last[mask]=end;
             }
         }
       }
       cout<<dp[(1<<n)-1]<<endl;
       print((1<<n)-1);

    }

    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值