当前位置: 首页 > 工具软件 > Doorman > 使用案例 >

【DP坑多】HNU2021校赛Doorman门童

狄宾实
2023-12-01

Description
Playf came to a mysterious place as a volunteer. His task was to receive contestants at the door of
the hotel. This profession is called doorman. It is known that the distance from the resting sofa to the door is L meters, and the walking speed of
playf is 1 m/s. Playf can only receive contestants when standing at the door (means that the distance
between playf and the door is 0), and playf can receive contestants instantly. At time 0, playf is standing at the door and his happiness is 0. When playf walks from the sofa to the
door, the happiness of playf decreases by x every second, while standing at the door, happiness
decreases by y every second, while walking toward the sofa, it decreases z every second, and when
sitting on the sofa, happiness increases by w every second. Playf can sit on the sofa only when the
distance between the playf and the sofa is 0. It is known that a total of n contestants will come to the hotel, the arrival time of the i-th contestant
is ai, and his patience is bi. For the i-th contestant, if playf does not stand at the door to receive him
during the time period [ai, ai+bi], playf will be fired due to his poor work. What’s more, each contestant
has a friendly value ci, when playf receives contestant i at time t , his happiness will increase ci *
(ai+bi-t). After receiving all the contestants, the task of playf is completed. Now playf wants to ask you, without getting fired, what is the maximum happiness he can get at the
moment the task is completed. 1≤L, ai, bi ≤10^9, 1≤ n ≤ 1000, 1≤ x,y,z,w, ci ≤200
It’s grantee that z ≤ y ≤ x and 2y ≤ x+z
Input
The first line contain six integers n, L, x, y, z, w, their meaning is as mentioned above. The following n lines, each line contain three integers ai, bi, ci, indicate i-th contestant’s arrival time, patience and friendly value. Output
Output one integer indicate the answer.Sample Input Output for Sample input
2 3 3 2 1 3
5 5 5
15 8 1
39
In [0,5], playf has been standing at the door, happiness decreases by 10
At time 5, playf received the first contestant, and happiness increased by 5
(5+5-5)=25
In [5,8], playf walks from the door to the sofa, happiness decreases by 13=3
In [8,20], playf has been sitting on the sofa, happiness increases by 12
3=36
In [20,23], playf walks from the sofa to the door, happiness decreases by 33=9
At time 23, playf received the second contestant. The happiness is increased by 1
(18+5-23)=0
The final happiness is -10+25-3+36-9=39

#include<bits/stdc++.h>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
#endif
using namespace std;
#define INF 0x3f3f3f3f 
#define N 2010
#define int long long
struct In{
	int a,b,c;
}in[N];
struct So{
	int t,f,g,id,r,c;//f:0起点1终点
	bool operator <(So x){
		return t<x.t;
	}
}so[N],cp[N];

struct Dp{
	int d,t,f,g,v,c;//t用于计算 v0可1不可 
}dp[N];//0为开始点 
int n,l,x,y,z,w;
signed main(){
	scanf("%d%d%d%d%d%d",&n,&l,&x,&y,&z,&w);
	for(int i=0;i<n;i++){
		scanf("%d%d%d",&in[i].a,&in[i].b,&in[i].c);
		so[2*i].t=in[i].a,so[2*i].f=0,so[2*i].g=2*i+1,so[2*i].id=2*i,so[2*i].c=in[i].c;
		so[2*i+1].t=in[i].a+in[i].b,so[2*i+1].f=1,so[2*i+1].g=2*i,so[2*i+1].id=2*i+1,so[2*i+1].c=in[i].c; 
	}
	memcpy(cp,so,sizeof(so));
	sort(cp,cp+2*n);
	for(int j=0;j<2*n;j++){
		so[cp[j].id].r=j+1;
	}
	dp[0].d=0,dp[0].t=0,dp[0].v=0; 
	for(int i=0;i<2*n;i++){
		dp[so[i].r].d=-INF;
		dp[so[i].r].f=so[i].f;
		dp[so[i].r].g=so[so[i].g].r;
		dp[so[i].r].t=so[i].t;
		dp[so[i].r].v=0;
		dp[so[i].r].c=so[i].c;
	}
	/*
	for(int i=0;i<=2*n;i++){
		printf("dp[%d]:d=%d,t=%d,f=%d,g=%d,v=%d,c=%d\n",i,dp[i].d,dp[i].t,dp[i].f,dp[i].g,dp[i].v,dp[i].c);
	}
	putchar('\n');
	*/
	int ml;
	for(int i=2*n;i>=0;i--){
		if(dp[i].f==0&&dp[i].t!=dp[i-1].t){//bug:注意重叠的情况,这样处理保证拿到全部后不会在走到沙发 
			ml=i;
			break;
		}
	}	
	for(int i=1;i<=2*n;i++){
		dp[i].d=dp[i-1].d-(dp[i].t-dp[i-1].t)*y;
		if(dp[i].f==0){
			dp[i].d+=dp[i].c*(dp[dp[i].g].t-dp[i].t);
		}
		//printf("door:dp[%d]:d=%d\n\n",i,dp[i].d);
		//bug:sum可能开始就有 
		int sum=(dp[i].f==0?(dp[dp[i].g].t-dp[i].t)*dp[i].c:0),temp;//愉快 
		//printf("sum:%d\n",sum);
		for(int j=i-1;j>=0;j--){
			int dt=dp[i].t-dp[j].t;
			int te=w*(dt-2*l)-(x+z)*l;
			if(dp[j].f==0&&dp[dp[j].g].t<dp[i].t&&j!=0){
				dp[j-1].v=1;
				//printf("tag:%d\n",j-1);
				//bug:去掉原来的break 
			}
			temp=sum;
			if(dp[j].f==0&&dp[dp[j].g].t>dp[i].t){//bug:要比时间因为有最后一次 
				sum+=(dp[dp[j].g].t-dp[i].t)*dp[j].c;
				//printf("dp[dp[j].g].t:%d dp[i].t:%d dp[j].c:%d\n",dp[dp[j].g].t,dp[i].t,dp[j].c);
				//printf("j:%d gtv:%d sum:%d\n",j,(dp[dp[j].g].t-dp[i].t)*dp[j].c,sum);
			}
			if(dp[j].v==1)break; 
			if(dt<=2*l)continue;
			if(j>=ml)continue;
			//printf("j=%d dt=%d te=%d sum=%d dp[%d].d+%d=%d\n",j,dt,te,sum,j,sum,dp[j].d+sum);
			dp[i].d=max(dp[i].d,dp[j].d+temp+te);//还是暂时不能用sum,因为可能重复算 
			//printf("now:dp[%d]:d=%d\n",i,dp[i].d);
		}
		//printf("dp[%lld]:d=%lld\n\n",i,dp[i].d);
	}
	int ma=-INF;
	for(int i=ml;i<=2*n;i++){
		//printf("to:%d dp:%d\n",i,dp[i].d);
		//bug:可能从门来也可以,要的是到了最后一个就不要再躺沙发了 
		//if(dp[ml].g==i)continue;
		ma=max(ma,dp[i].d);
	}//bug:做完就走 
	printf("%lld\n",ma);//bug:居然还要开 long long 
	return 0;
}
 类似资料: