P1004 方格取数
題目描述
設有 N \times NN×N 的方格圖 (N \le 9)(N≤9),我們將其中的某些方格中填入正整數,而其他的方格中則放入數字 00。如下圖所示(見樣例):
A
0 0 0 0 0 0 0 0
0 0 13 0 0 6 0 0
0 0 0 0 7 0 0 0
0 0 0 14 0 0 0 0
0 21 0 0 0 4 0 0
0 0 15 0 0 0 0 0
0 14 0 0 0 0 0 0
0 0 0 0 0 0 0 0
B
某人從圖的左上角的 AA 點出發,可以向下行走,也可以向右走,直到到達右下角的 BB 點。在走過的路上,他可以取走方格中的數(取走后的方格中將變為數字 00)。
此人從 AA 點到 BB 點共走兩次,試找出 22 條這樣的路徑,使得取得的數之和為最大。
輸入格式
輸入的第一行為一個整數 NN(表示 N \times NN×N 的方格圖),接下來的每行有三個整數,前兩個表示位置,第三個數為該位置上所放的數。一行單獨的 00 表示輸入結束。
輸出格式
只需輸出一個整數,表示 22 條路徑上取得的最大的和。
輸入輸出樣例
輸入 #1 復制
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
輸出 #1 復制
67
說明/提示
NOIP 2000 提高組第四題
*這道題一開始看到就像用兩次dp來做,第一次走到終點,算出最大距離,并把走過的方格置為
0,然后第二次從起點開始再用一次dp.后來有個數據死活A不了,百思不得其解,下載了一組測試用例,在草稿紙上花了圖才知道求的不是最優解。
測試用例如下:
7
1 3 2
1 4 3
2 3 3
3 3 3
5 5 4
6 5 4
7 3 2
7 5 4
0 0 0
原本是要輸出 25 但是這個只能輸出23
兩次dp代碼如下:
#include <iostream> #include <cstring> using namespace std; int main() {int s[20][20];memset(s,0, sizeof(s));int dp[20][20]; //dp[i][j]表示(1,1)--(N,N)的最大值int N;cin>>N;int a,b,c;memset(dp,0, sizeof(dp));memset(s,0, sizeof(s));int sum=0;while(cin>>a>>b>>c&&a||b||c){s[a][b]=c;}int Max_i,Max_j;for(int i=1;i<=N;i++){for(int j=1;j<=N;j++){dp[i][j]=max(dp[i-1][j],dp[i][j-1])+s[i][j];if(i==N&&j==N){Max_i=dp[i-1][j]>dp[i][j-1] ? i-1:i;Max_j=dp[i-1][j]>dp[i][j-1] ? j:j-1;sum=dp[N][N];s[N][N]=0;}}}while((Max_i!=1||Max_j!=1)&&Max_i>=1&&Max_i<=N&&Max_j>=1&&Max_j<=N){s[Max_i][Max_j]=0;int temp_i=Max_i;int temp_j=Max_j;Max_i=dp[temp_i][temp_j-1]>dp[temp_i-1][temp_j] ? temp_i:temp_i-1;Max_j=dp[temp_i][temp_j-1]>dp[temp_i-1][temp_j] ? temp_j-1:temp_j;}s[1][1]=0;memset(dp,0, sizeof(dp));for(int i=1;i<=N;i++){for(int j=1;j<=N;j++){dp[i][j]=max(dp[i-1][j],dp[i][j-1])+s[i][j];} }sum=sum+dp[N][N];cout<<sum<<endl;return 0;}下面我畫一張圖來解釋為什么不能兩次dp
上圖是上面那一組不能通過的測試用例,正確的走法是如下圖所示
這題我們要兩個人同時走,可能分別走也可以,是我沒想出來?
#include <iostream> #include <cstring> using namespace std;int main(){int s[20][20];memset(s,0, sizeof(s));int dp[20][20][20];int N;cin>>N;int a,b,c;memset(dp,0, sizeof(dp));memset(s,0, sizeof(s));while(cin>>a>>b>>c&&a||b||c){s[a][b]=c;}for(int k=2;k<=N+N;k++){for(int i1=1;i1<=N;i1++){for(int i2=1;i2<=N;i2++){if(k-i1<=N&&k-i1>=1&&k-i2<=N&&k-i2>=1){int temp=s[i1][k-i1];if(i1!=i2){temp+=s[i2][k-i2];}dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2-1]+temp);dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2-1]+temp);dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1-1][i2]+temp);dp[k][i1][i2]=max(dp[k][i1][i2],dp[k-1][i1][i2]+temp);}}}}cout<<dp[N+N][N][N];return 0;}總結
以上是生活随笔為你收集整理的P1004 方格取数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑上传,如何查看电脑上传速度
- 下一篇: 名表依波路borel_依波路手表排名 依