1. 程式人生 > >NYOJ 613免費餡餅 動態規劃解法

NYOJ 613免費餡餅 動態規劃解法

讀題:一開始看題感到無從下筆,看到T給出範圍後想到老師說看到引數給範圍便想一想能不能建陣列來解決。而這時認真看一下題,每一秒落在一個位置x上

不正好可以建一個數組 a【11】【100000】來儲存嗎;

構思:

由第一組測試資料

6
5 1
4 1
6 1
7 2
7 2
8 3

得到a陣列:


這樣便可由a【0】【5】用深度優先搜尋來找最大餡餅數——結果很明顯(超時)  ٩(๑❛ᴗ❛๑)۶

因為深搜太慢,且題目資料很大;

那麼就只有用DP(動態規劃)來做了

從a【0】【5】出發,時間過去一秒的前提下可以待在原地,可以向左,可以向右。

在時間為5秒及5秒以前


每一行的第一個(最後一個元素)只能由斜下方的元素左移一格(右移一格) 時間過一秒後得到(選擇其中最大的一格加上自己本身)

每行的第二(倒數第二)可以由下方的元素不動或左移一格(左移一格) 時間過一秒後得到  (選擇其中最大的一格加上自己本身)

每行的其他元素可由 其下方的 元素不動 或右下方元素左移或左下方元素右移得到   (選擇其中最大的一格加上自己本身)

到了5秒以後

每一行的第一和最後一個等於

斜下方的元素左移一格(右移一格) 或下方元素不動    時間過一秒後得到(選擇其中最大的一格加上自己本身)

a[0][T]+=max2(a[0][T-1],a[1][T-1]);
a[10][T]+=max2(a[10][T-1],a[9][T-1]);
其他的與5秒以前的第三種情況一樣,可由 其下方的 元素不動 或右下方元素左移或左下方元素右移得到   (選擇其中最大的一格加上自己本身)
這樣便得到了沒一格的最大餡餅數,在最後一秒的一行中選最大的便可
int max=0;
for(i=0;i<11;i++)if(a[i][maxT]>max)max=a[i][maxT];

完整程式碼如下:

#include<stdio.h> 
#include<string.h>
int a[11][100005];
int max2(int i,int n){
	if(i>n)return i;
	else return n;}
int max3(int x,int y,int z){
	if(x<y){int t=x;x=y;y=t;};
	if(x<z){int t=x;x=z;z=t;};
	if(y<z){int t=y;y=z;z=t;};
	return x;}
int main(){
	int i,n;
	while(scanf("%d",&n)!=EOF&&n!=0){
		memset(a,0,sizeof(a));
		int T,x,mt=0;;
		for(i=0;i<n;i++){
			scanf("%d%d",&x,&T);
			a[x][T]++;
			if(T>mt)mt=T; }
		int v=1;
		for(i=3;i<=7;i++){
			if(i==3)a[i][v+1]+=a[i+1][v];
			else if(i==4)a[i][v+1]+=max2(a[i][v],a[i+1][v]);
			else if(i==6)a[i][v+1]+=max2(a[i][v],a[i-1][v]);
			else if(i==7)a[i][v+1]+=a[i-1][v];
			else a[i][v+1]+=max3(a[i][v],a[i-1][v],a[i+1][v]); }
		v++;
		for(i=2;i<=8;i++){
			if(i==2)a[i][v+1]+=a[i+1][v];
			else if(i==3)a[i][v+1]+=max2(a[i][v],a[i+1][v]);
			else if(i==7)a[i][v+1]+=max2(a[i][v],a[i-1][v]);
			else if(i==8)a[i][v+1]+=a[i-1][v];
			else a[i][v+1]+=max3(a[i][v],a[i-1][v],a[i+1][v]); }
		v++;
		for(i=1;i<=9;i++){
			if(i==1)a[i][v+1]+=a[i+1][v];
			else if(i==2)a[i][v+1]+=max2(a[i][v],a[i+1][v]);
			else if(i==8)a[i][v+1]+=max2(a[i][v],a[i-1][v]);
			else if(i==9)a[i][v+1]+=a[i-1][v];
			else a[i][v+1]+=max3(a[i][v],a[i-1][v],a[i+1][v]); }
		v++;
		for(i=0;i<=10;i++){
			if(i==0)a[i][v+1]+=a[i+1][v];
			else if(i==1)a[i][v+1]+=max2(a[i][v],a[i+1][v]);
			else if(i==9)a[i][v+1]+=max2(a[i][v],a[i-1][v]);
			else if(i==10)a[i][v+1]+=a[i-1][v];
			else a[i][v+1]+=max3(a[i][v],a[i-1][v],a[i+1][v]); }
		if(mt<=5){
			int max=0;
			for(i=0;i<11;i++)if(a[i][mt]>max)max=a[i][mt];
			printf("%d\n",max); 
		}
		else{
			for(i=6;i<=mt;i++){
				a[0][i]+=max2(a[0][i-1],a[1][i-1]);
				a[10][i]+=max2(a[10][i-1],a[9][i-1]);
				for(int w=1;w<=9;w++)a[w][i]+=max3(a[w][i-1],a[w-1][i-1],a[w+1][i-1]);
			}
			int max=0;
			for(i=0;i<11;i++)if(a[i][mt]>max)max=a[i][mt];
			printf("%d\n",max);
		}
	}
}