Codeforces Round #436 (Div. 2)-背包&排序&输出状态-E. Fire

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值