Don‘t fear, DravDe is kind


/* 问题描述
  这一天,有一列车子排起了一排长队,必经之路是一个被魔王笼罩的山洞。每辆车的司机害怕魔王程度不同,所以每个司机有一些要求。
  车子有n台,排成一条长队,每辆车有4个属性:
  V ——这辆车的总价值,价值就是比如它其中的乘客和货物的价值
  c ——这辆车里面的人数量(司机表示自己也算一个乘客,司机和乘客不用区分开来)
  l ——在这辆车的前面需要总量正好为多少乘客的车(不多也不少),这车才敢开
  r ——在这辆车的后面需要总量正好为多少乘客的车(不多也不少),这车才敢开
  “前面需要总量正好为多少乘客的车”指的是驶在这辆车前面所有的车的乘客总数。
  “后面需要总量正好为多少乘客的车”指的是驶在这辆车后面所有的车的乘客总数。
  你不能改变每辆车在车队的相对顺序,但你可以安排某些车退出车队,保证依然在车队的每辆车都敢开了,即满足上述条件,并且剩下车的v的总量最大。
  -----------------------------
  简单来说,给您按输入顺序排列的n辆车,您需要删去里面的一些车(剩下的车仍然按原相对顺序排列)。
  使得对于每辆车,若它没被删去,设其为输入的第i辆车,
  要满足
  l[i]= sigma{c[j] | j<i 且第j辆车没被删去}
  r[i]= sigma{c[j] | j>i 且第j辆车没被删去}
  在满足这些条件前提下,要求sigma{V[i] | i没被删去} 最大,
  请输出这个最大值,并且递增输出没有被删去的车的标号。
输入格式
  输入的第一行为一个正整数n(1<=n<=10^5)——车的个数。
  接下来n行,每行四个整数,第i行的数字: vi, ci,li ,ri ,(1<=vi<=10^4 , 1<=ci<=10^5,0<=li,ri<=10^5),车子们从1开始编号,从车队的最前头开始算起。
输出格式
  第一行输出一个数k:会继续在这车队里的车的总数(注意我们的目标是让价值最大)。
  第二行k个数,递增输出继续在车队里的车的编号。
  请留心你不允许改变车的次序。如果答案不唯一,输出任意一个。
样例输入
5
1 1 0 3
1 1 1 2
1 1 2 1
1 1 3 0
2 1 3 0
样例输出
4
1 2 3 5
样例输入
5



1 0 3



1 1 0 3
10 1 2 1
2 2 1 1
10 1 1 2
3 1 3 0

0	1	2	3	4
	1
			3		
		11
				6		

样例输出
3
1 3 5
数据规模和约定
  对于20%的数据,n<=100
  对于50%的数据,n<=1000
  对于100%的数据,n<=100000
  对于100%的数据,1<=vi<=10^4 , 1<=ci<=10^5,0<=li,ri<=10^5 */

#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
#include<algorithm>
using namespace std;

typedef struct{
	int v,c,l,r,index;
}Node;


void input(int ,map<int,vector<Node> >*);

void solve(int *,int*,vector<Node> *,int);
void solve(int *p_max,int*p_sum,vector<Node> *sz,int sum,vector<int>*ans){
	int jl[sum][3];
	memset(jl,-1,(sum+1)*4*3);
	jl[0][0] = 0;
	
	
	
	int j,ii;
	int i;
	for(i = 0;i < (*sz).size();i++){
		int now = (*sz).at(i).l+(*sz).at(i).c,last = (*sz).at(i).l;
		//printf("now = %d  last = %d\n",now,last);
		
		if(jl[last][0] >= 0 && jl[last][0]+(*sz).at(i).v > jl[now][0]){
			jl[now][0] = jl[last][0]+(*sz).at(i).v;
			jl[now][1] = last;
			jl[now][2] = (*sz).at(i).index;
		}
	}
	
	
	
	if(jl[sum][0] > *p_max){
		*p_max = jl[sum][0];
		*p_sum = sum;
		(*ans).clear();
		int i = sum;
		while(i != 0){
			(*ans).push_back(jl[i][2]);
			i = jl[i][1];
		}
	}
	
}



void input(int n,map<int,vector<Node> > *maps){
	int i = 1;
	while(i <= n){
		Node node;
		scanf("%d%d%d%d",&node.v,&node.c,&node.l,&node.r);
		node.index = i;
		(*maps)[node.c+node.l+node.r].push_back(node);
		i++;
	}
	
}

int main(void) {
	
	int n;
	scanf("%d",&n);
	
	map<int,vector<Node> > maps;
	
	input(n,&maps);
	
	vector<int> ans;
	
	
	
	map<int,vector<Node> >::iterator iter = maps.begin();
	int max = 0,sum = -1;
	while(iter != maps.end()){
		solve(&max,&sum,&(iter->second),iter->first,&ans);
		iter++;
	}
	
	printf("%d\n",ans.size());
	
	int i;
	for(i = ans.size()-1;i >= 0;i--){
		printf("%d ",ans.at(i));
	}
	
	return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值