HDU10871003的一些感悟
Posted zzzyyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU10871003的一些感悟相关的知识,希望对你有一定的参考价值。
我是先做的1087,这个题的大意是两个人下棋每个棋子里有一个权值,这个权值代表你能获得的分数,你可以选择走这一步或者跳过。并且你的每一步都必须是上升的,否则就结束。最后获得分数最高的人获胜,现在要你求一下则么样获得这个最大值。
SAMPLE INPUT
3 1 3 2
4 1 2 3 4
4 3 3 2 1
0
SAMPLE OUTPUT
4
10
3
第一个数代表棋子的个数,接下来是每个棋子的权值,以零结尾。
这题就是求一列数的最长上升子序列。
解法一:用二重循环,但这个比较耗时。
具体思路是从第一个棋子开始选定一个棋子,然后从第一个棋子开始到选定棋子不断更新最大长度
新建一个数组DP
如果不规定是上升的话
1-》3-》2
dp[0]=1 dp[0]=1
dp[1]=3 dp[1]=dp[0]+dp[1]=4
dp[2]=2 dp[2]=dp[0]+dp[2]=3 dp[2]=dp[1]+dp[2]=5
规定上升需要删除
dp[2]=dp[1]+dp[2]=5 (3大于2)
所以可以用代码这样表示
a[1000]数组接收输入的数据,dp数组更新到每个位置的最长上升子序列的最大长度。
for(int i=0;i<n;i++)
{
dp[i]=a[i];
for(int j=0;j<i;j++)
{
if(a[j]<a[i]&&dp[j]+a[i]>dp[i])
dp[i]=dp[j]+dp[i];
maxm=max(dp[i],maxm);
}
AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int N,n[1010],dp[1010];
while(scanf("%d",&N)&&N)
{
int maxm=-1;
for(int i=0;i<N;i++)
scanf("%d",&n[i]);
for(int i=0;i<N;i++)
{
dp[i]=n[i];
for(int j=0;j<i;j++)
{
if(n[j]<n[i]&&dp[j]+n[i]>dp[i])
dp[i]=dp[j]+n[i];
maxm=max(dp[i],maxm);
}
}
cout<<maxm<<endl;
}
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int T,N,tempnum,tempsum,sum,fp,lp,begin,b=1;
scanf("%d",&T);
while(T--)
{
tempsum=0;
sum=-1001;
begin=0;
fp=0;
lp=0;
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&tempnum);
tempsum+=tempnum;
if(tempsum>sum)
{
sum=tempsum;
fp=begin;
lp=i;
}
if(tempsum<0)
{
tempsum=0;
begin=i+1;
}
}
printf("%s%d%s ","Case ",b,":");
cout<<sum<<" "<<fp+1<<" "<<lp+1<<endl;
if(T>0)cout<<endl;
b++;
}
以上是关于HDU10871003的一些感悟的主要内容,如果未能解决你的问题,请参考以下文章