HDU - 1074 Doing Homework HDU - 1074

利用二进制才实现dp

n个作业,一共有1<<n中情况。

枚举每一种情况,之后遍历每一个作业,如果当前情况下这个作业还没做,我们就不做任何处理。

如果当前作业做了,我们就让当前情况变成当前作业没做的那个情况下,之后没做的情况的值加上当前作业的值再减去当前作业需要扣除的分数(注意最低为0)。就是我们枚举的那个情况的值了




#include <iostream>  

#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <string>  
#include <queue>  
#include <algorithm>  
#include <map>  
#include <cmath>  
#include <iomanip>  
#define INF 99999999  
typedef long long LL;  
using namespace std;  
  
const int MAX=(1<<15)+10;  
int n;  
int dp[MAX],t[MAX],pre[MAX],dea[20],fin[20];//dp[i]记录到达状态i扣的最少分,t时相应的花去多少天了  
char s[20][110];  
  
void output(int x){  
    if(!x)return;  
    output(x-(1<<pre[x]));  
    printf("%s\n",s[pre[x]]);  
}  
  
int main(){  
    int T;  
    scanf("%d",&T);  
    while(T--){  
        scanf("%d",&n);  
        for(int i=0;i<n;++i)scanf("%s%d%d",&s[i],&dea[i],&fin[i]);  
        int bit=1<<n;  
        for(int i=1;i<bit;++i){//枚举到达状态i  
            dp[i]=INF;//初始化到达状态i的扣分   
            for(int j=n-1;j>=0;--j){//由于输入时按字符大小输入,而每次完成j相当于把j放在后面完成且下面判断是dp[i]>dp[i-temp]+score   
                int temp=1<<j;      //所以是n-1开始,如果下面判断是dp[i]>=dp[i-temp]+score则从0开始   
                if(!(i&temp))continue;//状态i不存在作业j完成则不能通过完成作业j到达状态i  
                int score=t[i-temp]+fin[j]-dea[j];//i-temp表示没有完成j的那个状态  
                if(score<0)score=0;//完成j被扣分数最小是0   
                if(dp[i]>dp[i-temp]+score){  
                    dp[i]=dp[i-temp]+score;  
                    t[i]=t[i-temp]+fin[j];//到达状态i花费的时间  
                    pre[i]=j;//到达状态i的前驱,为了最后输出完成作业的顺序   
                }   
            }  
        }  
        printf("%d\n",dp[bit-1]);  
        output(bit-1);//输出完成作业的顺序   
    }  
    return 0;  

}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值