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;
    }
    


  • 相关阅读:
    密码强度正则表达式 – 必须包含大写字母,小写字母和数字,至少8个字符等
    |DataDirectory|的使用
    SqlParameter的作用与用法
    C# 通过http post 请求上传图片和参数
    webuploader批量导入文件
    MVC使用Controller完成登录验证
    网页特效 模板素材
    C#中的Cookie 添加 读取 删除
    JS jquery jquery.wordexport.js 实现导出word
    初始配置JDK
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7016037.html
Copyright © 2011-2022 走看看