HDU--5280(dp或枚举)

来源:互联网 发布:相场模拟软件 编辑:程序博客网 时间:2024/05/18 22:14
官方题解:
这个题有很多O(n2)的算法,这里说一种:枚举每一个区间,在枚举区间的同时维护区间内的最小值和区间和,将最小值与P的大小进行比较,贪心地取最大值即可。注意若枚举到的区间是整个数组,则P的值是必须取的。当然也存在O(n)的做法:从左往右处理出dp1[i]=max(a[i],dp1[i1]+a[i]),同样从右往左处理出dp2[i]=max(a[i],dp2[i+1]+a[i]),再枚举要修改哪一个数,用两个数组更新答案即可。
我是用了两次dp,其实可以合成一个的,o(n2)的也是,每改一次dp一次,写的略丑。
#include<iostream>#include<cstring>#include<cstdio>#include<map>#include<cstring>#include<algorithm>#define INF 0x3f3f3f3f3f3F#define mem(a,b) memset(a,b,sizeof(a))using namespace std;typedef long long ll;typedef unsigned long long llu;const int maxd=1000+10;//---------------------ll a[maxd];ll dp[2][maxd];ll n,p;ll DP(){    dp[0][0]=max(a[0],(ll)0);    for(int i=1;i<n;++i)        dp[0][i]=max((ll)0,(ll)dp[0][i-1]+a[i]);   ll ans=a[0];    for(int i=1;i<n;++i){          dp[1][i]=dp[0][i-1]+a[i];          ans=max(ans,dp[1][i]);    }    return ans;}int main(){    freopen("1.txt","r",stdin);    int kase;    scanf("%d",&kase);    while(kase--)    {       scanf("%I64d%I64d",&n,&p);       for(int i=0;i<n;++i)        scanf("%I64d",&a[i]);       ll ans=-1000000000001;       for(int i=0;i<n;++i)       {           int tmp=a[i];           a[i]=p;           ans=max(ans,DP());           a[i]=tmp;       }       printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击