HDU-1087(Super Jumping! Jumping! Jumping!)(LCS)
Super Jumping! Jumping! Jumping!
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 31034 Accepted Submission(s): 13907
Problem Description
Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very popular in HDU. Maybe you are a good boy, and know little about this game, so I introduce it to you now.
The game can be played by two or more than two players. It consists of a chessboard(棋盘)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path.
Your task is to output the maximum value according to the given chessmen list.
![](https://i-blog.csdnimg.cn/blog_migrate/b69a36fbfe92ef60e13d861294653386.jpeg)
The game can be played by two or more than two players. It consists of a chessboard(棋盘)and some chessmen(棋子), and all chessmen are marked by a positive integer or “start” or “end”. The player starts from start-point and must jumps into end-point finally. In the course of jumping, the player will visit the chessmen in the path, but everyone must jumps from one chessman to another absolutely bigger (you can assume start-point is a minimum and end-point is a maximum.). And all players cannot go backwards. One jumping can go from a chessman to next, also can go across many chessmen, and even you can straightly get to end-point from start-point. Of course you get zero point in this situation. A player is a winner if and only if he can get a bigger score according to his jumping solution. Note that your score comes from the sum of value on the chessmen in you jumping path.
Your task is to output the maximum value according to the given chessmen list.
Input
Input contains multiple test cases. Each test case is described in a line as follow:
N value_1 value_2 …value_N
It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int.
A test case starting with 0 terminates the input and this test case is not to be processed.
N value_1 value_2 …value_N
It is guarantied that N is not more than 1000 and all value_i are in the range of 32-int.
A test case starting with 0 terminates the input and this test case is not to be processed.
Output
For each case, print the maximum according to rules, and one line one case.
Sample Input
3 1 3 2 4 1 2 3 4 4 3 3 2 1 0
Sample Output
4 10 3
注:这题是要求上升子序列的最大和。(与求最大上升子序列的长度类似。)
刚开始自己也毫无头绪,在看了大牛的博客后才理解。
//dp[i]表示保存的是以i为终点的上升子序列的和,通过for循环不断查找并更新最大子序列的和。
for(i=2;i<=n;i++)
{
t=0;
for(j=1;j<i;j++)
{ // a[i]>a[j]保证了查找的子序列,是上升的子序列 ,得到的和是上升子序列的和
if(a[i]>a[j])//在a[0]~a[i]中,比较所有a[0]~a[i]之间子序列的和 ,找出最大值
{
if(dp[j]>t)
t=dp[j];
}
dp[i]=a[i]+t;//找到最大子序列的和后,再加上a[i]自身值,从而得到前i个数的最大上升子序列和
}
}
//这与求最大上升子序列的长度类似,在求最大上升子序列的长度时,dp[i]存放的是以i为终点的上升子序列的长度 ,通过for循环不断更新并查找最大子序列长度。
for(i=2;i<=n;i++){
t=0;
for(j=1;j<i;j++)
{ // a[i]>a[j]保证了查找的子序列,是上升的子序列 ,得到的和是上升子序列的和
if(a[i]>a[j])//在a[0]~a[i]中,比较所有a[0]~a[i]之间子序列的和 ,找出最大值
{
if(dp[j]>t)
t=dp[j];
}
dp[i]=a[i]+t;//找到最大子序列的和后,再加上a[i]自身值,从而得到前i个数的最大上升子序列和
}
}
//这与求最大上升子序列的长度类似,在求最大上升子序列的长度时,dp[i]存放的是以i为终点的上升子序列的长度 ,通过for循环不断更新并查找最大子序列长度。
{
temp=0;
for(j=1;j<i;j++)//在前i-1个数中查找a[i]的最长子序列
{
if(a[i]>a[j])
{
if(dp[j]>temp)//这一句是保证temp记录的始终是最长的子序列元素个数 (具体参考下面的例子)
{
temp=dp[j];//更新temp值
}
}
}
dp[i]=temp+1;//temp表示在a[i]之前(即:a[1]~~a[i-1])的最长子序列的元素个数 ,+1表示把其自身加在内
}
这题告诉我们要学会变通,灵活运用所学知识点。
My solution:
/*2016.3.30*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[1050],a[1050];
//dp[i]表示保存的是以i为终点的最大的上升子序列的和
int main()
{
int i,j,k,n,m,t;
while(scanf("%d",&n)==1&&n)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
memset(dp,0,sizeof(dp));
dp[1]=a[1];
for(i=2;i<=n;i++)
{
t=0;
for(j=1;j<i;j++)
{ // a[i]>a[j]保证了查找的子序列,是上升的子序列 ,得到的和是上升子序列的和
if(a[i]>a[j])//在a[0]~a[i]中,比较所有a[0]~a[i]之间子序列的和 ,找出最大值
{
if(dp[j]>t)
t=dp[j];
}
dp[i]=a[i]+t;//找到最大子序列的和后,再加上a[i]自身值,从而得到前i个数的最大上升子序列和
}
}
t=0;
for(i=1;i<=n;i++)//从n个子序列和中找出最大值
if(dp[i]>t)
t=dp[i];
printf("%d\n",t);
}
return 0;
}
后来又做了此题,发现又不会做了,不知错在哪,汗,汗,汗,翻看了之前题解才发现错在哪。
My solution:
/*2016.4.21*/
已改过,可以AC.
#include<stdio.h>
#include<algorithm>
using namespace std;
int a[1100];
//int dp[1100];
long long sum[1100];
int main()
{
int i,j,k,n,m,t;
while(scanf("%d",&n)==1&&n)
{
t=0;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
//dp[1]=1;
sum[1]=a[1];
for(i=2;i<=n;i++)
{
//temp=0;
t=0;
for(j=1;j<i;j++)
{
if(a[i]>a[j])
{
if(sum[j]>t)//选取最大的子序列和
{
t=sum[j];
}
//if(dp[j]>temp) //而不是选取最长子序列,看了之前的博客才发现错在这
// {
// t=j;
// temp=dp[j];
// }
}
}
// dp[i]=temp+1;
sum[i]=t+a[i];
}
sort(sum+1,sum+n+1);
printf("%I64d\n",sum[n]);
}
return 0;
}