1. 程式人生 > >2018-暑假留校訓練賽(2)

2018-暑假留校訓練賽(2)

const 思路 round art cannot cto 方程 least 只需要

題目鏈接:https://vjudge.net/contest/237052#problem/A

Thanks a lot for helping Harry Potter in finding the Sorcerer‘s Stone of Immortality in October. Did we not tell you that it was just an online game ? uhhh! now here is the real onsite task for Harry. You are given a magrid S ( a magic grid ) having R rows and C columns. Each cell in this magrid has either a Hungarian horntail dragon that our intrepid hero has to defeat, or a flask of magic potion that his teacher Snape has left for him. A dragon at a cell (i,j) takes away |S[i][j]| strength points from him, and a potion at a cell (i,j) increases Harry‘s strength by S[i][j]. If his strength drops to 0 or less at any point during his journey, Harry dies, and no magical stone can revive him.

Harry starts from the top-left corner cell (1,1) and the Sorcerer‘s Stone is in the bottom-right corner cell (R,C). From a cell (i,j), Harry can only move either one cell down or right i.e., to cell (i+1,j) or cell (i,j+1) and he can not move outside the magrid. Harry has used magic before starting his journey to determine which cell contains what, but lacks the basic simple mathematical skill to determine what minimum strength he needs to start with to collect the Sorcerer‘s Stone. Please help him once again.

Thanks a lot for helping Harry Potter in finding the Sorcerer‘s Stone of Immortality in October. Did we not tell you that it was just an online game ? uhhh! now here is the real onsite task for Harry. You are given a magrid S ( a magic grid ) having R rows and C columns. Each cell in this magrid has either a Hungarian horntail dragon that our intrepid hero has to defeat, or a flask of magic potion that his teacher Snape has left for him. A dragon at a cell (i,j) takes away |S[i][j]| strength points from him, and a potion at a cell (i,j) increases Harry‘s strength by S[i][j]. If his strength drops to 0 or less at any point during his journey, Harry dies, and no magical stone can revive him.

Harry starts from the top-left corner cell (1,1) and the Sorcerer‘s Stone is in the bottom-right corner cell (R,C). From a cell (i,j), Harry can only move either one cell down or right i.e., to cell (i+1,j) or cell (i,j+1) and he can not move outside the magrid. Harry has used magic before starting his journey to determine which cell contains what, but lacks the basic simple mathematical skill to determine what minimum strength he needs to start with to collect the Sorcerer‘s Stone. Please help him once again.

Input (STDIN):

The first line contains the number of test cases T. T cases follow. Each test case consists of R C in the first line followed by the description of the grid in R lines, each containing C integers. Rows are numbered 1 to R from top to bottom and columns are numbered 1 to C from left to right. Cells with S[i][j] < 0 contain dragons, others contain magic potions.

Output (STDOUT):

Output T lines, one for each case containing the minimum strength Harry should start with from the cell (1,1) to have a positive strength through out his journey to the cell (R,C).

Constraints:

1 ≤ T ≤ 5

2 ≤ R, C ≤ 500

-10^3 ≤ S[i][j] ≤ 10^3

S[1][1] = S[R][C] = 0

Sample Input:

3
2 3
0 1 -3
1 -2 0
2 2
0 1
2 0
3 4
0 -2 -3 1
-1 4 0 -2
1 -2 -3 0

Sample Output:

2
1
2

Explanation:

Case 1 : If Harry starts with strength = 1 at cell (1,1), he cannot maintain a positive strength in any possible path. He needs at least strength = 2 initially.

Case 2 : Note that to start from (1,1) he needs at least strength = 1.

題目大意:給你一副圖,問你從圖左上點走到右下點,所需要的最小初始分數,因為每走到一點就要加上改點的值,且你要保證在中途每點上你的分數的值至少為1,你的走路方式只能往右走或下走。

個人思路:剛看到直接dfs,加上剪枝,改了六七遍,都是超時,然後意識到不能用dfs,立馬想到dp來做,一直是正向思維,一直在想怎麽寫出狀態轉移方程,不過一直沒寫出來,因為如果用正向來做的話,不僅僅要保留該點的當前分數值,還要保留起點到該點所需的分數值,這樣就控制不了了,但是逆向思維,從終點往回退,只需要保留該點到終點所需要的分值,而不需要考慮該點還剩多少分值,很簡單就能做出來

dp[i][j]表示從該點到終點所需要的分值

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<math.h>
#include<algorithm>
#include<set>
typedef long long ll;
using namespace std;
#define INF 1e9+7
int a[510][510];
int dp[510][510];//dp[i][j]表示從該點到終點所需要的最少分數
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
                scanf("%d",&a[i][j]);
        }
        dp[n-1][m-1]=1;//每個點最小是1,初始化終點是1
        for(int i=n-1;i>=0;i--)
        {
            for(int j=m-1;j>=0;j--)
            {
                if(i!=n-1&&j==m-1)
                {
                    dp[i][j]=max(1,dp[i+1][j]-a[i][j]);
                }
                else if(i==n-1&&j!=m-1)
                {
                    dp[i][j]=max(1,dp[i][j+1]-a[i][j]);
                }
                else if(i!=n-1&&j!=m-1)
                {
                    dp[i][j]=max(1,min(dp[i+1][j]-a[i][j],dp[i][j+1]-a[i][j]));
                }
            }
        }
        printf("%d\n",dp[0][0]);
    }
    return 0;
}

  

2018-暑假留校訓練賽(2)