1. 程式人生 > >HDU 1176(類似數字三角形的題,很經典,值得仔細理解的dp思維)

HDU 1176(類似數字三角形的題,很經典,值得仔細理解的dp思維)

ron 接下來 開始 bre 就是 變形 style 的人 %d

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=1176

免費餡餅

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 60927 Accepted Submission(s): 21380


Problem Description 都說天上不會掉餡餅,但有一天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 分析: 一開始真的不知道是個數字三角形的變形題,思考了很久,最後看了別人的題解。。。。。。。 分析: 一個人站在5的位置 第一秒能到的位置:4,5,6 第二秒能到的位置:3,4,5,6,7 第三秒能到達的位置:2,3,4,5,6,7,8 依次類推: 第一秒 4,5,6 第二秒: 3,4,5,6,7 第三秒: 2,3,4,5,6,7,8 第四秒: 1,2,3,4,5,6,7,8,9
第五秒:0,1,2,3,4,5,6,7,8,9,10 第六秒:0,1,2,3,4,5,6,7,8,9,10 非常的類似數字三角形,回顧一下數字三角形:從頂向下走(只能向下或者左下),怎麽走使得走過的路權值之和最大 回到這個問題,這個問題的權值就是某個時刻某個位置餡餅的個數 dp[i][j]:第i秒j位置餡餅的個數 是不是非常非常類似數字三角形? 每次移動的話只要三個選擇:向左一個單位,向右一個單位,不動 所以狀態轉移方程: dp[i][j]=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))+dp[i][j]; 跟數字三角形一樣,倒推 註意初始化: dp數組初始化為0,表示一開始所有時刻,所有位置餡餅個數為0 每個時刻每個位置餡餅的個數要隨著輸入寫好 找到時刻的最大值,這樣從時刻最大值倒數循環 代碼如下:
#include<bits/stdc++.h>
using namespace std;
#define max_v 100005
int dp[max_v][20];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n==0)
            break;
        memset(dp,0,sizeof(dp));
        int t=-1;
        for(int i=0;i<n;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            dp[y][x]++;
            if(y>t)
                t=y;
        }
        for(int i=t-1;i>=0;i--)
        {
            for(int j=10;j>=0;j--)
            {
                dp[i][j]=max(dp[i+1][j],max(dp[i+1][j-1],dp[i+1][j+1]))+dp[i][j];
            }
        }
        printf("%d\n",dp[0][5]);
    }
    return 0;
}

  

HDU 1176(類似數字三角形的題,很經典,值得仔細理解的dp思維)