[洛谷] P1004 方格取数 Apare_xzc dp
[洛谷] P1004 方格取数
题目链接<—
题面:
样例输入:
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
样例输出
67
思路:
如果是走一次的话,那是最经典(简单)的动态规划问题。令dp[x][y]表示从起点A到点(x,y)路径的最大和,那么dp转移方程为:
dp[x][y] = max(dp[x-1][y] , dp[x][y-1]) + a[x][y]
我们贪心地认为走两次的最大值就是第一次的最大值加上第一次拿完后第二次的最大值之和
80分代码
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int a[20][20]; ///存地图
int dp[20][20]; ///存答案
struct Node
{
int x,y; ///坐标
Node(int xx=0,int yy=0):x(xx),y(yy){}
}pre[20][20],node; ///记录前驱节点
int ans,n;
void solve();
int main()
{
//freopen("in.txt","r",stdin);
int x,y,val;
while(cin>>n)
{
ans = 0;
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
while(cin>>x>>y>>val&&(x||y||val))
{
a[x][y] = val;
}
solve();
solve();
cout<<ans<<endl;
}
return 0;
}
void solve()
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
if(i==1&&j==1)
{
pre[i][j] = Node(0,0);
dp[i][j] = a[i][j]; ///记录最大值
}
else if(i==1) ///格子在第一行,不在第一列,只能从左边转移而来
{
pre[i][j] = Node(i,j-1);
dp[i][j] = a[i][j]+dp[i][j-1];
}
else if(j==1) ///格子在第一列,只能从上往下转移而来
{
pre[i][j] = Node(i-1,j);
dp[i][j] = a[i][j]+dp[i-1][j];
}
else ///格子不在第一行,也不在第一列,可以从左边和上边转移而来
{
if(dp[i-1][j]>dp[i][j-1]) ///上边的更优
{
pre[i][j] = Node(i-1,j);
dp[i][j] = a[i][j]+dp[i-1][j];
}
else
{
pre[i][j] = Node(i,j-1);
dp[i][j] = a[i][j]+dp[i][j-1];
}
}
}
}
ans += dp[n][n];
int x = n;
int y = n;
while(x&&y)
{
a[x][y] = 0;
node = pre[x][y];
x = node.x;
y = node.y;
}
}
因为可以免费下载第一组错误,我们得到
Sample Input 3
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
Sample Output 3
25