zoukankan      html  css  js  c++  java
  • 第七届省赛赛前交流赛部分题解

    A题: Yougth's Game[Ⅲ]( 区间dp )


    这是在省赛前热身赛出的题目,可能是题目中实用到博弈的思想,非常多人都在做,并且在尝试暴力。

    可是没有人往dp的方向上想。


    题目类型:动态规划+博弈
    分析:题意描写叙述的非常清楚,就是选择在两端取数,当前取的数不仅可以影响下一次的结果,并且可以影响后面的结果。

    。又是一个求最优值,那么是不是可以往dp的方向上想了。区间dp

    定义状态dp[ i ] [ j ] 为从 i 到 j 上A的得分,那么B的得分就是sum(i,j)-dp[ i ] [ j ]
    转移方程 : dp[i][j]=max(dp[i][j],a[i]+(sum[j]-sum[i]-dp[i+1][j])); 表示区间i--j取第一个
    dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1])); 表示区间i--j取最后一个

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 1200;
    int a[N],dp[N][N],n;
    int b[N];
    int main()
    {
        while(~scanf("%d",&n)&&n)
        {
            b[0]=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                b[i]=b[i-1]+a[i];
            }
            for(int l=1;l<=n;l++)
            {
                for(int i=1,j=l;j<=n;i++,j++)
                {
                    dp[i][j]=-99999999;
                    dp[i][j]=max(dp[i][j],a[i]+(b[j]-b[i]-dp[i+1][j]));
                    dp[i][j]=max(dp[i][j],a[j]+(b[j-1]-b[i-1]-dp[i][j-1]));
                }
            }
            printf("%d
    ",dp[1][n]-(b[n]-dp[1][n]));
        }
        return 0;
    }
    



    E:Yougth's Game[II]

    题目类型:组合博弈   
    事实上就是一个sg函数,sg函数解说:解说

    分析:题目能够抽象成一个取石子游戏,三堆石子x,y,x*y。那么就抽象成了经典的取石子游戏。
    每次能够取得数目是给定的,谁最后取完谁赢。
    求出三个数的sg值,然后异或就是ans

    代码:
     
    #include<stdio.h>
    #include<string.h>
    #include <string>
    #include <iostream>
    using namespace std;
    
    const int N = 10008;
    int s[108],t;
    int sg[N];
    bool hash[N];
    void sg_solve(int *s,int t,int N)   //N求解范围 S[]数组是能够每次取的值。t是s的长度。
    {
        int i,j;
        memset(sg,0,sizeof(sg));
        for(i=1;i<=N;i++)
        {
            memset(hash,0,sizeof(hash));
            for(j=0;j<t;j++)
                if(i - s[j] >= 0)
                    hash[sg[i-s[j]]] = 1;
            for(j=0;j<=N;j++)
                if(!hash[j])
                    break;
            sg[i] = j;
        }
    }
    
    int main()
    {
        int x,y;
        while(~scanf("%d%d",&x,&y))
        {
            int n;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
                scanf("%d",&s[i]);
            sg_solve(s,n,N);
            if((sg[x]^sg[y]^sg[x*y])==0)
                printf("Yougth is best
    ");
            else
                printf("No
    ");
        }
        return 0;
    }
            

    H题:合并游戏

    题目类型:状态压缩动态规划

    分析:给出每两个石子合并蹦出的金币,求全部石子合并之后蹦出的金币,分析能够发现不同的合并顺序会有不一样的结果。然后满足最优子结构的性质。那就是确定某几个石子合并的到的最大金币永远是确定的,那么我们能够用dp来求解。而这个题目恰好是一个从0到全部合并的一个过程。用二进制压缩来表示状态。


    定义状态:dp【st】表示状态st中为1的合并起来的最大值

    状态转移方程:dp[state-(1<<j)]=max(dp[state-(1<<j)], dp[state]+a[i][j]);(每次都从 i 为1的点转移过来)

    代码:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int N = 12;
    int a[N][N],dp[1<<N];
    int main()
    {
        int n;
        while(~scanf("%d",&n)&&n)
        {
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    scanf("%d",&a[i][j]);
            memset(dp,0,sizeof(dp));
            for(int state=(1<<n); state>=0; state--)
            {
                for(int i=0; i<n; i++)  //枚举初始合并点
                {
                    if(state&(1<<i))
                        continue;
                    for(int j=0; j<n; j++)   //跟哪一个合并
                    {
                        if(!(state&(1<<j)))
                            continue;
                        if(i==j)
                            continue;
                        int newstate=state-(1<<j);
                        dp[newstate]=max(dp[newstate], dp[state]+a[i][j]);
                    }
                }
            }
            int maxnum=0;
            for(int i=0; i<(1<<n); i++)
                maxnum=max(maxnum, dp[i]);
            printf("%d
    ", maxnum);
        }
        return 0;
    }
    


  • 相关阅读:
    Session的使用与Session的生命周期
    Long-Polling, Websockets, SSE(Server-Sent Event), WebRTC 之间的区别与使用
    十九、详述 IntelliJ IDEA 之 添加 jar 包
    十八、IntelliJ IDEA 常用快捷键 之 Windows 版
    十七、IntelliJ IDEA 中的 Maven 项目初体验及搭建 Spring MVC 框架
    十六、详述 IntelliJ IDEA 创建 Maven 项目及设置 java 源目录的方法
    十五、详述 IntelliJ IDEA 插件的安装及使用方法
    十四、详述 IntelliJ IDEA 提交代码前的 Code Analysis 机制
    十三、IntelliJ IDEA 中的版本控制介绍(下)
    十二、IntelliJ IDEA 中的版本控制介绍(中)
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7016037.html
Copyright © 2011-2022 走看看