Atcoder Beginner Contest 266 problem D 题解
Atcoder Beginner Contest 266 problem D 题解
题目链接:点我
题目大意
一条路上有\(5\)个格子,分别是\(0,1,2,3,4\)。一共有\(N\)条蛇,每条蛇有三个属性:\(t_i,x_i,w_i\)分别表示这条蛇的出现的时间,出现的位置和这条蛇的价值。
现在,一个人要来抓蛇。他初始在\(0\)的位置。每一秒钟,这个人可以向前一格,向后一格,或者在原地不动。第\(i\)条蛇会在\(t_i\)的时间从\(x_i\)的格子钻出来。如果此时这个人恰好在\(x_i\)的位置,那么他就可以抓住这条蛇,并获得它的价值\(w_i\)。问这个人可以获得的总价值最大是多少?
样例输入1
3
1 0 100
3 3 10
5 4 1
样例输出1
101
样例解释1
- 在\(0\)号格子等待\(1\)秒钟,然后在时间\(1\)抓住\(1\)号蛇,得到价值\(100\)。
- 前往\(4\)号格子,在时间\(5\)抓住\(3\)号蛇,得到价值\(1\)。
总价值为\(101\),这是最大的了。
样例输入2
3
1 4 1
2 4 1
3 4 1
样例输出2
0
样例输入3
10
1 4 602436426
2 1 623690081
3 3 262703497
4 4 628894325
5 3 450968417
6 1 161735902
7 1 707723857
8 2 802329211
9 0 317063340
10 2 125660016
样例输出3
2978279323
数据范围
- \(1 \leq N \leq 10^5\)
- \(0 < t_1 < t_2 < ... <t_N \leq 10^5\)
- \(0 \leq x_i \leq 4\)
- \(1 \leq w_i \leq 10^9\)
- 所有输入均为整型数。
解析
本蒟蒻看到这道题,第一反应是贪心,并且分了两种情况来贪:
- 根据时间贪心
- 根据价值贪心
不过,本蒟蒻很快就 Hack 掉了贪心,证明如下:
1.如果根据时间贪心,那么这组数据就不正确:
2
4 54 1
5 0 100
根据时间来看,我们应该走到\(4\)号格子得到价值\(1\)。但实际上,我们如果一直待着不动,那么我们会得到价值\(100\)。显然后者更优,但并不满足时间贪心的条件。
2.如果根据价值贪心,那么这组数据就不正确:
3
4 4 5
6 1 2
7 0 4
根据价值贪心的话,我们会选择走到\(4\)号格子得到价值\(5\),然后就得不到更多价值了。但实际上,若果我们只走到\(1\)号格子上并等待到\(6\)秒,然后第\(7\)秒再走到\(0\)号格子,这样可以抓住两条蛇得到价值\(6\)。显然后者更优,但并不满足价值贪心的条件。
至此,贪心全面崩盘。
贪心不行,那肯定就是\(dp\)来凑了嘛!我们观察到时间\(t\)是严格递增的,给出的格子数目又很小,于是,我们可以定义一下状态:
\(f[i][j]\)表示第\(i\)秒时这个人在\(j\)号格子时能获得的最大价值数。
由于这个人每秒可以选择做三件事,于是\(f\)数组可以这样转移:$$f[i][j]=max(f[i-1][j-1],f[i-1][j],f[i-1][j+1])$$
如果说在时间\(i\),格子\(j\)上刚好有一条蛇出现的话,那么就要加上这条蛇的价值:$$f[i][j]+=a[id]$$ \(id\)表示\(i\)时间出现的是第几条蛇。可以用二分求得。
代码实现
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+5;
int n;
int t[N],x[N],w[N];
long long ans,f[N][6];//注意数据范围,要用long long存储答案
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>t[i]>>x[i]>>w[i];
memset(f,-0x3f,sizeof f);
f[0][0]=0;//初始化。0时间时在0号格子,什么也没做,所得到的的价值是0
for(int i=1;i<=t[n];i++){
int res=lower_bound(t+1,t+n+1,i)-t,X,W;
if(t[res]!=i) X=233;
else X=x[res],W=w[res];//用二分找到当前时间是否有蛇
for(int j=0;j<=4;j++){
f[i][j]=max(f[i-1][j+1],max(f[i-1][j-1],f[i-1][j]));
if(X==j) f[i][j]+=W;//如果有蛇,加上价值
}
}
for(int i=0;i<=4;i++) ans=max(ans,f[t[n]][i]);//对五个格子都要扫一遍,找到最大值
cout<<ans;
}
完结撒花~~~

浙公网安备 33010602011771号