打卡信奥刷题(2763)用C++实现信奥题 P3800 Power 收集

P3800 Power 收集

题目背景

据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了。

然而当时灵梦在 Power 达到 MAX 之前,不具有“上线收点”的能力,所以她想要知道她能收集多少 P 点,然而这个问题她答不上来,于是她找到了学 OI 的你。

题目描述

可以把游戏界面理解成一个 NNNMMM 列的棋盘,有 KKK 个格子上有 P 点,其价值为 val⁡(i,j)\operatorname{val}(i,j)val(i,j)

初始灵梦可以选择在第一行的任意一个格子出发,每秒她必须下移一格。

灵梦具有一个左右移动的速度 TTT,可以使她每秒向左或右移动至多 TTT 格,也可以不移动,并且在单次移动中不能折返。移动可视为瞬间完成,不经过路途上的点,只能获得目标格子的 P 点。

求最终她能获得的所有 P 点的价值总和最大是多少?

输入格式

第一行四个整数,N,M,K,TN,M,K,TN,M,K,T

接下来 KKK 行每行 333 个整数 x,y,vx,y,vx,y,v,代表第 xxx 行第 yyy 列有一个 val⁡\operatorname{val}valvvv 的 P 点,数据保证一个格子上最多只有 111 个 P 点。

输出格式

一个整数,表示灵梦能获得的 P 点的价值总和的最大值。

输入输出样例 #1

输入 #1

3 3 4 1
1 1 3
1 2 1
2 2 3
3 3 3

输出 #1

9

说明/提示

对于 40%40\%40% 的测试点,1≤N,M,T,K≤2001 \le N,M,T,K \le 2001N,M,T,K200

对于 100%100\%100% 的测试点,1≤N,M,T,K≤40001 \le N,M,T,K \le 40001N,M,T,K40000≤v≤1000 \le v \le 1000v100N,M,K,TN,M,K,TN,M,K,T 均为整数。

by-szc

C++实现

#include<cstdio>
#include<ctype.h>
#include<cstring>
#define int long long
#define max(a,b) a>b?a:b
const int MARX = 4e3+10;
int n,m,k,t, now,ans;
int f[MARX][MARX];
int head=1,tail=1;//手写双端队列 
int q[MARX]={9223372036854775807};//为q[0]赋一个极大值,来防止插入元素时越界 
inline int read(){
	int fl=1,w=0;char ch=getchar();
	while(!isdigit(ch) && ch!='-') ch=getchar();
	if(ch=='-') fl=-1;
	while(isdigit(ch)){w=w*10+ch-'0',ch=getchar();}
	return fl*w;
}
void in(int x){
	while(f[now-1][x]>f[now-1][q[tail]] && tail>=head) 
	  tail--;//取出队尾小于插入元素的数 , 以保证单调性 
	q[++tail]=x;//插入队尾 
}
int find(int x){
	if(x+t<=m)in(x+t);//将能转移到x点 的 最后一个元素 x+t 插入队列 
	while(q[head]+t<x) head++;//找到队首第一个能够转移到x的点 
	return q[head]; 
}
signed main(){
	n=read(),m=read(),k=read(),t=read();
	while(k--)	{
	  int x=read(),y=read(),w=read();
	  f[x][y]=w;
	}
	for(now=2;now<=n;now++)	{
	  for(int i=1;i<=t;i++) in(i);//初始化单调队列 , 满足能够 转移j=1的点 
	  for(int j=1;j<=m;j++) f[now][j]+=f[now-1][find(j)];// 进行转移 
	  head=tail=1 , q[1]=0;//清空队列 
	}
	
	for(int i=1;i<=m;i++)//取得最大值 
	  ans=max(ans,f[n][i]);
	printf("%lld",ans);
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值