Codeforces Round #436 E. Fire

来源:互联网 发布:为什么黑客都用python 编辑:程序博客网 时间:2024/06/05 21:00

Title:Polycarp is in really serious trouble — his house is on fire! It's time to save the most valuable items. Polycarp estimated that it would taketi seconds to savei-th item. In addition, for each item, he estimated the value ofdi — the moment after which the itemi will be completely burned and will no longer be valuable for him at all. In particular, ifti ≥ di, theni-th item cannot be saved.

Given the values pi for each of the items, find a set of items that Polycarp can save such that the total value of this items is maximum possible. Polycarp saves the items one after another. For example, if he takes item a first, and then item b, then the itema will be saved in ta seconds, and the item b — in ta + tb seconds after fire started.

Input:The first line contains a single integern (1 ≤ n ≤ 100) — the number of items in Polycarp's house.

Each of the following n lines contains three integersti, di, pi (1 ≤ ti ≤ 20,1 ≤ di ≤ 2 000,1 ≤ pi ≤ 20) — the time needed to save the itemi, the time after which the item i will burn completely and the value of item i.

Output:In the first line print the maximum possible total value of the set of saved items. In the second line print one integerm — the number of items in the desired set. In the third line printm distinct integers — numbers of the saved itemsin the order Polycarp saves them. Items are 1-indexed in the same order in which they appear in the input. If there are several answers, print any of them.
题目大意:假设房间发生火灾,但房间内有n件物品,题目给定每件物品的t(救援所需时间),d(毁掉的时间点),p价值,求你能救援的最大价值。
题目思路:01背包+打印路径(很不情愿的打了这九个字符)。可以发现这题的特别之处在于多了一个d的限制,对于d,d小的应该先取,因为假设能取多个物品,先取d小的总是更好。(也可以从01背包的角度出发,如果按d升序排序,则当前决策不影响以前决策)
转移方程易得:dp[i][j]=max(dp[i-1][j],dp[i-1][j-ti]+pi)(同01背包,条件限制在代码中解释)
这题我理解了好久,兜了一天才做出来,没错,就是这么low~不过值得!
#include<bits/stdc++.h>using namespace std;struct node{int t,d,p;    int ind;    bool operator<(const node& n) const{    return d<n.d;}}item[110];int dp[105][2005],path[105][2005];int main(){int n;while(~scanf("%d",&n)){for(int i=1;i<=n;i++){scanf("%d %d %d",&item[i].t,&item[i].d,&item[i].p);item[i].ind=i;}sort(item+1,item+n+1);memset(dp,0,sizeof(dp));memset(path,0,sizeof(path));for(int i=1;i<=n;i++){for(int j=0;j<item[i].d;j++){//重要点,因为超出毁掉时间的并没有意义 dp[i][j]=dp[i-1][j];if(j<item[i].t) continue;if(dp[i-1][j-item[i].t]+item[i].p>dp[i][j]){dp[i][j]=dp[i-1][j-item[i].t]+item[i].p;path[i][j]=1;}}}                //dp[n][item[n].d-1]并非最大值,值得思考 ,因为第23行的缘故,忽略了毁掉时间点后的价值,        //item[n].d-1也有可能是被忽略的点               int maxj=0,pos;for(int i=0;i<2001;i++){if(dp[n][i]>maxj){maxj=dp[n][i];pos=i;}}printf("%d\n",maxj);vector<int> v;for(int i=n;i>=1;i--){if(path[i][pos]){v.push_back(item[i].ind);pos-=item[i].t;}}printf("%d\n",v.size());for(int i=v.size()-1;i>=0;i--) printf("%d ",v[i]);puts("");}return 0;} 
就这样了,就算把这题过了。但总觉得不够好,希望大家讨论一下。

原创粉丝点击