A - Max Sum
思路;
(1)要记录开头和结尾,那么就开一个结构体,用来储存当前最大值和开头位置和结束位置
(2)判断 如果加的数 temp 大于 temp 和前面的最大值 (即新加的数temp自己单独更大,而前面的最大值为负)刷新开头和结尾
(3)如果加的temp为正,而前面的最大值正(保证不与上面情况重复),那么说明,加上temp一定最大值一定会变大,结尾加1
下面AC代码
#include<stdio.h>
#include<string.h>
int a[100000];
int main()
{
int t,step=0;
scanf("%d",&t);
while(t--)
{
int n,low=1,high=1,pos1=1,pos2=1;
step++;
if(step!=1)
{
printf("\n");
}
scanf("%d",&n);
memset(a,0,sizeof(a));
a[0]=-1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int max=a[1],temp=a[1];
for(int i=2;i<=n;i++)
{
if(a[i]>a[i]+temp)
{
temp=a[i];
low=i;
high=i;
}
else
{
temp+=a[i];
high++;
}
if(temp>max)
{
max=temp;
pos1=low;
pos2=high;
}
}
printf("Case %d:\n%d %d %d\n",step,max,pos1,pos2);
}
return 0;
}
在网上,我找到一个大神代码,和我思路一样,但是比我这简单明了
大神代码的变量有点多,我先介绍一下
t 测试数据组数 n 每组数据的长度 temp 当前取的数据 pos1 最后MAX SUM的起始位置 pos2 最后MAX SUM的结束位置 max 当前得到的MAX SUM now 在读入数据时,能够达到的最大和 x 记录最大和的起始位置,因为不知道跟之前的max值的大小比,所以先存起来
#include <iostream>
using namespace std;
int main()
{
int t,n,temp,pos1,pos2,max,now,x,i,j;
cin>>t;
for (i=1;i<=t;i++)
{
cin>>n>>temp;
now=max=temp;
pos1=pos2=x=1;
for (j=2;j<=n;j++)
{
cin>>temp;
if (now+temp<temp)
now=temp,x=j;
else
now+=temp;
if (now>max)
max=now,pos1=x,pos2=j;
}
cout<<"Case "<<i<<":"<<endl<<max<<" "<<pos1<<" "<<pos2<<endl;
if (i!=t)
cout<<endl;
}
return 0;
}
只有这短短几行,比我少一半
我好菜啊!
分析一下大神代码优点
大神把输入和过程中的循环合并了(我的是先输入,再进行过程,二者完全分开)
大神定义变量集中定义的,而我是想起来,随便找个地方补一下,或者变量不够了,再补
这样的代码很乱,没有什么可读性,下次注意
再说说思路;
刚开始我并没有想出来,
下面我来总结一下,下次遇到类似题应该如何想,如何找思路
(1)一般来说,动规过后出现都是最优解
但是这题不是,动规后的结果可能是最优解,也可能不是
这时候需要我们开个变量来储存这个最优解
(2)因为这子链是连续的,那我们肯定要判断一下这个链是否在那里断开从新开一个新的链
如果不开新链,那我们就一直加,找最优情况,存起来
当时我一直的思路是;
普通DP,每次DP找最优解,但是根本就没法找,
难道要每加一个数,搜索一下?
其实这个思路是挺不好想的,