免費餡餅 dp

題目描述

都說天上不會掉餡餅,但有一天gameboy正走在回家的小徑上,忽然天上掉下大把大把的餡餅。說來gameboy的人品實在是太好了,這餡餅別處都不掉,就掉落在他身旁的10米範圍內。餡餅如果掉在了地上當然就不能吃了,所以gameboy馬上卸下身上的揹包去接。但由於小徑兩側都不能站人,所以他只能在小徑上接。由於gameboy平時老呆在房間裏玩遊戲,雖然在遊戲中是個身手敏捷的高手,但在現實中運動神經特別遲鈍,每秒種只有在移動不超過一米的範圍內接住墜落的餡餅。現在給這條小徑如圖標上座標:


爲了使問題簡化,假設在接下來的一段時間裏,餡餅都掉落在0-10這11個位置。開始時gameboy站在5這個位置,因此在第一秒,他只能接到4,5,6這三個位置中其中一個位置上的餡餅。問gameboy最多可能接到多少個餡餅?(假設他的揹包可以容納無窮多個餡餅)
 

Input
輸入數據有多組。每組數據的第一行爲以正整數n(0<n<100000),表示有n個餡餅掉在這條小徑上。在結下來的n行中,每行有兩個整數x,T(0<T<100000),表示在第T秒有一個餡餅掉在x點上。同一秒鐘在同一點上可能掉下多個餡餅。n=0時輸入結束。
 

Output
每一組輸入數據對應一行輸出。輸出一個整數m,表示gameboy最多可能接到m個餡餅。
提示:本題的輸入數據量比較大,建議用scanf讀入,用cin可能會超時。


Sample Input
6 5 1 4 1 6 1 7 2 7 2 8 3 0
 

Sample Output
4
 
用動態規劃的思想,將0秒第5點作爲最終狀態,逆向求解。要想知道0秒5點最多能接到多少餡餅,我們只要知道1秒時在4,5,6三點分別最多能接到多少月餅,然後取其最大值加上0秒5點時能接到的餡餅數就行了。
用dp[i][j]表示第i秒在j點處能接到的最大餡餅數,於是我們得到方程dp[i][j]=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1])+dp[i][j];
從最大時間開始,逆向求得dp[0][5]即爲最終解
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int Max(int a,int b,int c){
	int x=max(a,b);
	x=max(x,c);
	return x;
}
int dp[100002][11];
int main() {
	std::ios::sync_with_stdio(false);
	int n;
	while(cin>>n) {
		if(n==0)
			break;
		memset(dp,0,sizeof(dp));
		int x,y,max_time;
		for(int i=0; i<n; i++){
			cin>>y>>x;
			dp[x][y]++;
			max_time=max(x,max_time);
		}
		for(int i=max_time;i>=0;i--){
			dp[i][0]=max(dp[i+1][0],dp[i+1][1])+dp[i][0];
			for(int j=1;j<10;j++){
				dp[i][j]=Max(dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1])+dp[i][j];
			}
			dp[i][10]=max(dp[i+1][10],dp[i+1][9])+dp[i][10];
		}
		cout<<dp[0][5]<<endl;
	}
}



 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章