• HihoCoder1338 A Game (区间DP)


    <题目链接>

    题目大意:

    两个人轮流从一个序列中取数,他们都面临同样的二选一决策:是拿走最左边的数,还是拿走最右边的数?问先手最多能够得到的分数是多少。

    解题分析:

    一道比较经典的DP,因为每次只能从数组的两端取走一个数,所以每次面对的数组都只可能是一段连续的子数组。我们不妨假设$dp[l][r]$表示对于数组$A[i]~A[j]$,先手能够获得的最多得分。于是状态的转移就不难得出了。

    枚举所有区间:

    $l==r$的时候,肯定是$dp[l][r]=arr[l]$

    而对于其他区间大于1的情况,$dp[l][r]=max(dp[l][r],((sum[r]-sum[l-1])-min(dp[l+1][r],dp[l][r-1])))$

    官方题解 >>> 

    递推DP

    #include <bits/stdc++.h>
    using namespace std;
    
    #define N int(1e3+5)
    int n,dp[N][N],arr[N],sum[N];
    
    int main(){
        scanf("%d",&n);
        sum[0]=0;
        for(int i=1;i<=n;i++)scanf("%d",&arr[i]),sum[i]=sum[i-1]+arr[i];
        memset(dp,-0x3f,sizeof(dp));
        for(int i=n;i>=1;i--){
            dp[i][i]=arr[i];
            for(int j=i+1;j<=n;j++){
                dp[i][j]=max(dp[i][j],(sum[j]-sum[i-1])-min(dp[i+1][j],dp[i][j-1]));
            }
        }
        printf("%d
    ",dp[1][n]);
    }

    记忆化搜索

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e3+5;
    int n,arr[N],dp[N][N],sum[N];
    
    int DP(int l,int r){
        if(l>r)return 0;
        if(dp[l][r]!=-1)return dp[l][r];
        dp[l][r]=-1e9;
        if(l==r)dp[l][r]=arr[l];
        else dp[l][r]=max(dp[l][r],(sum[r]-sum[l-1])-min(DP(l+1,r),DP(l,r-1)));
        return dp[l][r];
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&arr[i]),sum[i]=sum[i-1]+arr[i];
        }
        memset(dp,-1,sizeof(dp));
        printf("%d
    ",DP(1,n));
    }
  • 相关阅读:
    将图片转成二进制并生成Base64编码,可以在网页中通过url查看图片
    <bean:wirte>的用法
    bean标签库Struts标签库
    <bean:write/>标签的format属性
    ByteArrayOutputStream和ByteArrayInputStream详解
    <bean:write>的用法
    FLASH寿命测试!
    波特率,kbps,Mbps含义
    printf()函数是格式化输出!
    Qt学习Qt中的C++
  • 原文地址:https://www.cnblogs.com/00isok/p/10640232.html
Copyright © 2020-2023  润新知