題意與分析
中文題就不講題意了。我是真的菜,菜出聲。
不妨思考一下,限制了我們決策的有哪些因素?一,所在的位置;二,所在的時間。還有嗎?沒有了,所以設為第i秒在j處的最大餡餅數,有:
是不是很顯然?然後就去快樂做題了對不對?
你就會想:從小到大推還是從大到小推?
從大到小推。因為如果從小到大推,無法反映出一次只能移動一格的特性;相反,從大到小推只需要最後直接求dp[0][5]即可。
這題說明了對於狀態轉移方程的思考一定要徹底,不能想當然。
程式碼
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define MP make_pair
#define PB push_back
#define fi first
#define se second
#define ZERO(x) memset((x), 0, sizeof(x))
#define ALL(x) (x).begin(),(x).end()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define QUICKIO \
ios::sync_with_stdio(false); \
cin.tie(0); \
cout.tie(0);
using namespace std;
template<typename T>
T read()
{
T tmp; cin>>tmp;
return tmp;
}
int f[100005][12],dp[100005][12],n;
int main()
{
QUICKIO
while(cin>>n)
{
if(!n) break;
ZERO(f); ZERO(dp);
// dp[i][j] 第i秒在第j米處能獲得的最多餡餅數目
// dp[i][j] = max(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+f[i][j]
int maxsec=0;
rep(i,1,n)
{
int x,y; cin>>x>>y;
f[y][x]++;
maxsec=max(y,maxsec);
}
// cout<<maxsec<<endl;
per(i,maxsec-1,0)
{
//cout<<i<<":\n";
rep(j,0,10)
{
//if(i==1 && j<4 && j>6) continue;
int maxans=-1;
if(j-1>=0) maxans=max(f[i+1][j-1],maxans);
maxans=max(f[i+1][j],maxans);
if(j+1<=10) maxans=max(f[i+1][j+1],maxans);
f[i][j]=maxans+f[i][j];
}
/*
rep(j,0,10)
{
cout<<f[i][j]<<" ";
}
cout<<endl;
*/
}
cout<<f[0][5]<<endl;
}
return 0;
}