HDU1087、1003的一些感悟

我是先做的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<iostream>
#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;
 }
}
1003一开始我也沿用1087的方法试着做,用个二重循环发现超时了。后来看了别人的代码发现了原来不需要存储数据,直接输入一个处理一个就行。
看完别人代码之后自己写还WA了两小时,,,,,,后来发现在原来在当前累加和小于零时应该把当前累加的和置为零而不是把当前最大值置为零,看到后表示要哭了。
AC代码:
#include<iostream>
#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\n","Case ",b,":");
  cout<<sum<<" "<<fp+1<<" "<<lp+1<<endl;
  if(T>0)cout<<endl;
  b++;
 }
}

猜你喜欢

转载自www.cnblogs.com/zzzyyy/p/9860748.html