简单动态规划题(这题目名字好长啊、、、),好像我以前看到了那啥类似的最长上升子序列的题。题目大意:在杭电有这么一种棋类游戏,在棋盘中有起点和终点,起点和终点之间的点用数字标记,代表到达该点可获得的分数,每个人只能从起点出发,每次走一步走到下一个点就能获得该点的分数(走步时不能走到比当前点分数小的点上,也不能往回走),可以一次跨越多个点但前提是该点分数比走步前的点的分数高,比如直接从起点走到终点(起点视为分数最小,终点视为分数最大)。给你每个点的分数,求从起点到达终点后可以获得的最大分数。
我的解题思路:我们假设dp[i]是从起点到达i点时可获得的最大分数,num[i]是i点的分数,那么容易通过题意得知该点的状态转移公式为dp[i] = max(dp[i], dp[x1] + num[i], ....dp[xn] + num[i]),其中xn是每一个点分数不大于num[i]的点且在点i前面的点。首先初始化的话dp[i] = num[i],这是毋庸置疑的。然后根据状态转移方程可知答案就是其中最大的dp。
下面是我的解题代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1111
int n;
int num[N]; //存储该点的分数
int dp[N]; //存储到达该点可得的最大分
void Read(); //输入
void DataProcess(); //解题
int main()
{
while (~scanf("%d", &n))
{
if (n == 0) break;
Read();
DataProcess();
}
return 0;
}
void Read()
{
for (int i=1; i<=n; ++i)
{
scanf("%d", &num[i]);
dp[i] = num[i]; //附带初始化
}
dp[0] = num[0] = 0; //初始化,重要部分
return;
}
void DataProcess()
{
int ans = 0;
for (int i=1; i<=n; ++i)
{
for (int j=i+1; j<=n; ++j)
{
if (num[j] > num[i])
{
dp[j] = max(dp[j], dp[i] + num[j]);
}
}
ans = max(dp[i], ans);
}
printf("%d\n", ans);
return;
}