zoukankan      html  css  js  c++  java
  • uva 10891 Game of Sum(区间dp)

    题目连接:10891 - Game of Sum


    题目大意:有n个数字排成一条直线,然后有两个小伙伴来玩游戏, 每个小伙伴每次可以从两端(左或右)中的任意一端取走一个或若干个数(获得价值为取走数之和), 但是他取走的方式一定要让他在游戏结束时价值尽量的高,最头疼的是两个小伙伴都很聪明,所以每一轮两人都将按照对自己最有利的方法去取数字,请你算一下在游戏结束时,先取数的人价值与后取数人价值之差(不要求绝对值)。


    解题思路:这道题目想了一晚上,死憋着不看题解, 结果写出的代码有点渣,dpx[i][j]表示在当前第i个数到第j个数中先取数的人可以达到的最高价值, dpy[i][j]为后取者最高可以达到的最高值。每次根据传入的参数flag判断是该谁去石子, 通过引用返回最优解。


    注意:数字可以为负数,所以标记的时候要注意, 我是重新开了个数组vis.


    #include <stdio.h>
    #include <string.h>
    const int N = 105;
    const int MAX = -0x3f3f3f3f;
    int n, num[N], sum[N], dpx[N][N], dpy[N][N], vis[N][N];
    
    void search(int a, int b, int& x, int& y, int flag) {
        int &A = dpx[a][b], &B = dpy[a][b];
        if (a + 1 == b)
    	A = num[b], B = 0;
    
        if (!vis[a][b]) {
    	int s, f;
    	A = sum[b] - sum[a], B = 0;
    	for (int i = a + 1; i < b; i++) {
    	    search(i, b, s, f, !flag);
    	    if (flag && f + sum[i] - sum[a] > A)
    		A = f + sum[i] - sum[a], B = s;
    	    else if (!flag && s + sum[i] - sum[a] > A)
    		A = s + sum[i] - sum[a], B = f;
    
    	    search(a, i, s, f, !flag);
    	    if (flag && f + sum[b] - sum[i] > A)
    		A = f + sum[b] - sum[i], B = s;
    	    else if (!flag && s + sum[b] - sum[i] > A)
    		A = s + sum[b] - sum[i], B = f;
    	}
        }
        vis[a][b] = 1;
    
        if (flag)
    	x = B, y = A;
        else
    	x = A, y = B;
    }
    
    void solve() {
        int s, f;
    
        memset(dpx, MAX, sizeof(dpx));
        memset(dpy, MAX, sizeof(dpy));
        memset(vis, 0, sizeof(vis));
    
        search(0, n, s, f, 0);
        printf("%d
    ", s - f);
    }
    
    int main() {
        while (scanf("%d", &n) == 1 && n) {
    	// Read;
    	memset(num, 0, sizeof(num));
    	memset(sum, 0, sizeof(sum));
    	for (int i = 1; i <= n; i++) {
    	    scanf("%d", &num[i]);
    	    sum[i] = sum[i - 1] + num[i];
    	}
    
    	solve();
        }
        return 0;
    }



    参考别人的题解,写了下面这个代码,因为两个小伙伴都是按照对自己最有利的方式取数字,那可以看成是一个过程,而确定区间a 到 b的最优解之后, 用sum(a, b) -  最优解就是后取数字的小伙伴可以取到的价值(只有两个人在玩,不是1拿就是2拿), 后取小伙伴的价值坑定是要尽量小自己拿到的才有可能越大。


    #include <stdio.h>
    #include <string.h>
    const int N = 105;
    const int MAX = 1 << 30;
    int max(int a, int b) { return a > b ? a : b; }
    int min(int a, int b) { return a < b ? a : b; }
    
    int n, dp[N][N], vis[N][N], num[N], sum[N];
    
    void read() {
        memset(dp, 0, sizeof(dp));
        memset(vis, 0, sizeof(vis));
        sum[0] = 0;
    
        for (int i = 1; i <= n; i++) {
    	scanf("%d", &num[i]);
    	sum[i] = sum[i - 1] + num[i];
        }
    }
    
    int solve(int a, int b) {
        if (a >= b)	    return 0;
        if (vis[a][b])   return dp[a][b];
        int ans = -MAX, cnt = b - a;
        vis[a][b] = 1;
        for (int i = 1; i <= cnt; i++)
    	ans = max(ans, sum[b] - sum[a] - min(solve(a + i, b), solve(a, b - i)));
        dp[a][b] = ans;
        return ans;
    }
    
    int main() {
        while (scanf("%d", &n), n) {
    	read();
    	printf("%d
    ", solve(0, n) * 2 - sum[n]);
        }
        return 0;
    }
    



  • 相关阅读:
    CS224n, lec 10, NMT & Seq2Seq Attn
    CS231n笔记 Lecture 11, Detection and Segmentation
    CS231n笔记 Lecture 10, Recurrent Neural Networks
    CS231n笔记 Lecture 9, CNN Architectures
    CS231n笔记 Lecture 8, Deep Learning Software
    CS231n笔记 Lecture 7, Training Neural Networks, Part 2
    pytorch坑点排雷
    Sorry, Ubuntu 17.10 has experienced an internal error
    VSCode配置python插件
    tmux配置与使用
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3320288.html
Copyright © 2011-2022 走看看