引子
一道简单背包,只是记忆方面卡了很久
题目描述
Polycarp惹了很大麻烦——他的房子着火了!由于火势太大,短时间内无法灭火。设大火燃烧的时间为0时刻,Polycarp想从大火中带走价值总和尽量多的物品。每次他只能带走一个,且营救两件物品的时间间隔为0。分别给出挽救第i件物品需要的时间为ti,开始燃烧的时间di(在d时间开始燃烧就不能再挽救该物品了),该物品的价值pi。在di时刻,第i件物品将被彻底烧毁,对他来说将不再有任何价值;如果ti≥di,那么第i件物品不能得救。
假设他从第0时刻开始营救物品,求他能从大火中能够带走物品的最大价值总和,并输出物品总数以及救援物品的顺序(物品的编号为输入的顺序)
输入格式
第一行: 物品总数n(1<=n<=100) 以下n行,每行分别三个整数ti(1<=ti<=20),di(1<=di<=2000),pi(1<=pi<=20)
输出格式
第一行: 能带走的最大的价值总和
第二行: 这些物品的数量 一行,数与数用空格分隔开,分别是能带走物品的编号(按读入顺序)
样例
样例输入 1
3
3 7 4
2 6 5
3 7 6
样例输出 1
11
2
2 3
样例输入 2
2
5 6 1
3 3 5
样例输出 2
1
1
1
代码时间
#include<bits/stdc++.h>
using namespace std;
int n,dp[2005],f[2005][2005],ANS,t;
struct Fire{
int t,d,p,num;
}a[105];
stack<int>fire;
void print(int i,int j){
if(i<=0||j<=0)return;
if(j>=a[i].d)print(i,j-1);
else if(f[i][j]==1){
fire.push(a[i].num);
print(i-1,j-a[i].t);
}
else print(i-1,j);
}
bool cmp(Fire x,Fire y){return x.d<y.d;}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].t>>a[i].d>>a[i].p;
a[i].num=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=a[i].d-1;j>=a[i].t;j--){
if(dp[j-a[i].t]+a[i].p>dp[j]){
dp[j]=dp[j-a[i].t]+a[i].p;
f[i][j]=1;
}
}
}
for(int i=0;i<=2000;i++)ANS=max(ANS,dp[i]);
for(int i=0;i<=2000;i++){
if(ANS==dp[i]){
t=i;
break;
}
}
cout<<ANS<<endl;
print(n,t);
cout<<fire.size()<<endl;
while(!fire.empty()){
cout<<fire.top()<<" ";
fire.pop();
}
return 0;
}