http://codeforces.com/contest/864/problem/E
给定若干个文件。
和整理他们花费的时间,他们的截止时间,和他们的价值。
问如何弄 价值最大。并输出文件数整理的顺序。和文件数量。
是背包。但是没想到怎么背。
先对截至日期排序。
dp[j]是截止到时间j。最大价值。
找到最大价值。然后再背包的过程中,保留用到i时的j(时间)。
然后从后往前,记录。
#include<bits/stdc++.h>
/* 是想到背包的思路。
但是不够清晰。
先判断,截至之间 小于要完成之间的
肯定不可以。
然后对 截至时间排序。
背包。
*/
using namespace std;
const int maxn=2e2;
const int maxm=2e5+1000;
struct Node{
int lim,cost,v,id;
}node[maxn];
vector<int>q;
int m;
bool cmp2(Node a,Node b){
return a.lim<b.lim;
}
int dp[maxm];
int vis[maxn][maxm];
int main()
{ while(~scanf("%d",&m)){
q.clear();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&node[i].cost,&node[i].lim,&node[i].v);
node[i].id=i;
}
sort(node+1,node+m+1,cmp2);
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++){
for(int j=node[i].lim;j>node[i].cost;j--){
if(dp[j]<dp[j-node[i].cost]+node[i].v){
dp[j]=dp[j-node[i].cost]+node[i].v;
vis[i][j]=1;
}
}
}
int ans=0;
for(int i=0;i<=node[m].lim;i++){
if(dp[i]>dp[ans]){
ans=i;
}
}
printf("%d\n",dp[ans]);
/*for(int i=1;i<=m;i++){
for(int j=1;j<=node[i].lim;j++){
printf("%d ",vis[i][j]);
}
cout<<endl;
}*/
for(int i=m;i>=1;i--){
if(vis[i][ans]){
q.push_back(node[i].id);
ans-=node[i].cost;
//cout<<ans<<endl;
//vis[i][ans]=false;
}
}
printf("%d\n",q.size());
for(int i=q.size()-1;i>=0;i--){
if(i==q.size()-1)
printf("%d",q[i]);
else
printf(" %d",q[i]);
}
printf("\n");
}
return 0;
}