codeforces 127 201C 双向DP

来源:互联网 发布:excel跨工作簿引用数据 编辑:程序博客网 时间:2024/06/05 11:47
有n个点排成一行,每两个点有一个权值。现在你可以从任何一个点出发,去遍历其他点,每经过两个相邻点之间的边,边的权值就会减1,求最多能走的步数
用两个dp数组记录往左走和往右走的最大步数
dp1[i][0]表示从i往左走最多能走的步数
dp1[i][1]表示往左走并回到i最多能走的步数
 
dp2同理
然后遍历一遍就可得答案
View Code
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100010;long long num[maxn];long long dp1[maxn][2],dp2[maxn][2];inline long long  max(long long  a,long long b){    return a>b?a:b;}inline void  Max(long long &ans,long long cmp){    if(cmp>ans) ans=cmp;}int main(){    int n,i,j,k;    scanf("%d",&n);    for(i=2;i<=n;i++) scanf("%lld",&num[i]);    dp1[1][0]=0;dp1[1][1]=0;    for(i=2;i<=n;i++)    {        if(num[i]>1) dp1[i][1]=dp1[i-1][1]+num[i]/2*2;        else dp1[i][1]=0;        if(num[i]&1) dp1[i][0]=dp1[i-1][0]+num[i];        else dp1[i][0]=max(dp1[i][1],dp1[i-1][0]+num[i]-1);    }    dp2[n][0]=0;dp2[n][1]=0;    for(i=n-1;i>=1;i--)    {        if(num[i+1]>1) dp2[i][1]=dp2[i+1][1]+num[i+1]/2*2;        else dp2[i][1]=0;        if(num[i+1]&1) dp2[i][0]=dp2[i+1][0]+num[i+1];        else dp2[i][0]=max(dp2[i][1],dp2[i+1][0]+num[i+1]-1);    }    long long ans=0;    for(i=1;i<=n;i++)    {        Max(ans,dp1[i][1]+dp2[i][0]);        Max(ans,dp2[i][1]+dp1[i][0]);    }    printf("%I64d\n",ans);//好悲剧,竟然用了%lld,害的我找了半天    return 0;}

 

同类型的题poj2479