问题描述
在大家不辞辛劳的帮助下,TT 顺利地完成了所有的神秘任务。
神秘人很高兴,决定给 TT 一个奖励,即白日做梦之捡猫咪游戏。
捡猫咪游戏是这样的,猫咪从天上往下掉,且只会掉在 [0, 10] 范围内,具体的坐标范围如下图所示。
TT 初始站在位置五上,且每秒只能在移动不超过一米的范围内接住掉落的猫咪,如果没有接住,猫咪就会跑掉。例如,在刚开始的一秒内,TT 只能接到四、五、六这三个位置其中一个位置的猫咪。
喜爱猫咪的 TT 想要接住尽可能多的猫咪,你能帮帮他吗?
Input
多组样例。每组样例输入一个 m (0 < m < 100000),表示有 m 只猫咪。
在接下来的 m 行中,每行有两个整数 a b (0 < b < 100000),表示在第 b 秒的时候有一只猫咪掉落在 a 点上。
注意,同一个点上同一秒可能掉落多只猫咪。m = 0 时输入结束。
Output
输出一个整数 x,表示 TT 可能接住的最多的猫咪数。
Sample input
6
5 1
4 1
6 1
7 2
7 2
8 3
0
Sample output
4
解题思路
这是一个dp题,我们按照时间来进行状态转移,设置数组dp[i][j][k],表示第 i i i秒,第 j j j个位置能接到猫的数量,k=1表示TT在这个位置接到猫,k=0表示TT没有到这个位置,这个位置存在的猫。最终结果就是最后一秒,所有位置k=1的最大值。
状态转移方程就是
dp[i][j][1]=dp[i][j][0]+max(dp[i-1][j-1][1],max(dp[i-1][j][1],dp[i-1][j+1][1]));
然后再考虑一下边界情况就可以了。
完整代码
//#pragma GCC optimize(2)
//#pragma G++ optimize(2)
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <climits>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=100000+10;
int a,b,maxtime,ans,m,dp[maxn][20][2];//dp[i][j]第i秒,位置j接到的最大数量,第三维度[0]表示不在这里,[1]表示在这里
int getint(){
int x=0,s=1; char ch=' ';
while(ch<'0' || ch>'9'){ ch=getchar(); if(ch=='-') s=-1;}
while(ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar();}
return x*s;
}
int main(){
//ios::sync_with_stdio(false);
//cin.tie(0);
while(cin>>m && m!=0){
maxtime=ans=0;
memset(dp,0,sizeof(dp));
for (int i=1; i<=m; i++){
cin>>a>>b;
dp[b][a][0]++;
maxtime=max(maxtime,b);
}
dp[0][5][1]=1;//别忘了减去
for (int i=1; i<=maxtime; i++){
for (int j=0; j<=10; j++){
if(j>0 && max(dp[i-1][j-1][1],max(dp[i-1][j][1],dp[i-1][j+1][1]))!=0)
dp[i][j][1]=dp[i][j][0]+max(dp[i-1][j-1][1],max(dp[i-1][j][1],dp[i-1][j+1][1]));
else if(max(dp[i-1][j][1],dp[i-1][j+1][1])!=0)
dp[i][j][1]=dp[i][j][0]+max(dp[i-1][j][1],dp[i-1][j+1][1]);
}
}
for (int i=1; i<=10; i++){
ans=max(ans,dp[maxtime][i][1]);
}
cout<<ans-1<<endl;
}
return 0;
}