1. 程式人生 > >Codeforces Round #436 E. Fire(背包dp+輸出路徑)

Codeforces Round #436 E. Fire(背包dp+輸出路徑)

include 多少 bsp 否則 ems 思路 pan while using

題意:失火了,有n個物品,每個物品有價值pi,必須在時間di前(小於di)被救,否則就要被燒毀。救某個物

    品需要時間ti,問最多救回多少價值的物品,並輸出救物品的順序。

Examples

Input
3
3 7 4
2 6 5
3 7 6

Output
11
2
2 3

Input
2
5 6 1
3 3 5

Output

1
1
1

思路:有點像一個背包,dp數組記錄的是當前時間所能獲得的最大價值,轉移方程dp[j]=max(dp[j],dp[j-t[i].ti]+t[i].w)
    path[i][j]表示到i號物品j時間的狀態時救的物品編號(這裏是從0開始)
    emmmmm 具體的在代碼中加以註釋。

代碼:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn=2010;
struct node{
int ti,en,w,op;
}t[110];
int dp[maxn],path[110][maxn],a[110];

bool cmp(node x,node y){
if(x.en!=y.en)return x.en<y.en;
else return x.ti<y.ti;
}


int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>t[i].ti>>t[i].en>>t[i].w;
t[i].op=i+1;
//op為每個物品的標號,題目要求從1開始
}
memset(dp,0,sizeof(dp));
memset(path,-1,sizeof(path));//開始全部置為-1
sort(t,t+n,cmp);
int ma=0;
for(int i=0;i<n;i++){
ma=max(ma,t[i].en);
if(i!=0){
for(int j=0;j<t[i].ti;j++)path[i][j]=path[i-1][j];
//時間小於所需的營救時間,那麽就不救,等於上一狀態
}
for(int j=t[i].en-1;j>=t[i].ti;j--){
if(dp[j]<dp[j-t[i].ti]+t[i].w){
dp[j]=dp[j-t[i].ti]+t[i].w;
path[i][j]=i;
//如果救,那麽就更新dp數組以及path數組為該物品
}
else if(i>0){
path[i][j]=path[i-1][j];
//如果不救,那麽還是等於上一狀態
}
}
}
int sum=0,temp=0;
for(int i=0;i<=ma;i++){
if(dp[i]>sum){
sum=dp[i];
temp=i;
//取出最大價值以及在最大價值的情況下,救完最後一個物品的時間
}
}
int k=n-1,c=0;
while(temp>0){
a[c++]=t[path[k][temp]].op;
temp-=t[path[k][temp]].ti;
k--;
k=path[k][temp];
//反著記錄下路徑
}
cout<<sum<<endl<<c<<endl;
for(int i=c-1;i>=0;i--){
if(i!=c-1)cout<<‘ ‘;
cout<<a[i];
//倒敘輸出
}
cout<<endl;
return 0;
}

Codeforces Round #436 E. Fire(背包dp+輸出路徑)