• NOIP模拟 Game


    题意:

    有n个带权球,A和B两个人,A先手拿球,一开始可以拿1个或2个,如果前一个人拿了k个,那么当前的这个人只能那k或k+1个,如果当前剩余的球不足,那么剩下的球都作废,游戏结束。假设两个人都是聪明人,每个人都会想方设法设获得比对方更多的球。问A最多能B多拿多少。

    分析:

    可以将先手取1n的最优值看做一个问题,先手取2n又是一个新的子问题,这样递归下去,便可求解。
    (f[i][k])表示从第i个开始,可以取k或k+1个,先手取比对方多出的最大值(可能是负数)。
    考虑用记忆化搜索:
    (f[i][k] = max(sum[i, i + k - 1] + f[i + k][k], sum[i, i + k] + f[i + k + 1][k + 1]))
    注意递归边界及条件。

    记忆化搜索的常数极大,考试时明明写的正解都被卡飞了,改了一个小小的初始化就A了,还是多写递推吧。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<ctime>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    namespace IO{
        template<typename T>
        inline void read(T &x){
            T i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
            x = i * f;
        }
        template<typename T>
        inline void wr(T x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
    }using namespace IO;
    
    const int N = 2e4 + 50, OO = 2e9 + 5;
    int T, n;
    int a[N], sum[N];
    typedef pair<int,int> P;
    int f[N][250];
    int vst[N][250], vt;
    
    inline void  chkmx(int &x, const int &y){
        if(x < y) x = y;
    }
    
    inline int F(int x, int k){
    //	if(f[x][k] != -OO) return f[x][k];
        if(vst[x][k] == vt) return f[x][k];
        vst[x][k] = vt;
        if(x > n - k + 1)
    		return f[x][k] = 0;
        int ret = -OO;
        if(x <= n - (k + 1) + 1)
            chkmx(ret, sum[x + k] - sum[x - 1] - F(x + k + 1, k + 1));
        chkmx(ret, sum[x + k - 1] - sum[x - 1] - F(x + k, k));
        return f[x][k] = ret;
    }
    
    int main(){
        freopen("game.in", "r", stdin);
        freopen("game.out", "w", stdout);
        read(T);
        while(T--){
            read(n);
            sum[0] = 0;
            for(register int i = 1; i <= n; i++) read(a[i]), sum[i] = sum[i - 1] + a[i];
    //        for(register int i = 1; i <= n; i++)
    //            for(register int j = 0; j <= 200; j++)
    //                f[i][j] = -OO;
            vt++;
            wr(F(1, 1));
            putchar('
    ');
        }
        return 0;
    }
    
    
  • 相关阅读:
    spring boot 配置示例
    MyBatis 常用标签用法
    http请求头部常用参数
    CentOS7使用firewalld打开关闭防火墙与端口
    java8 base64
    MD5工具类
    各种远程登录工具
    MySql 常用命令
    spring-boot-mybaits 开启事务
    springboot 项目打包到 linux下无法 运行
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7756383.html
Copyright © 2020-2023  润新知