sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)

Description
In the two-player game "Two Ends", an even number of cards is laid out in a row. On each card, face up, is written a positive integer. Players take turns removing a card from either end of the row and placing the card in their pile. The player whose cards add up to the highest number wins the game. Now one strategy is to simply pick the card at the end that is the largest -- we‘ll call this the greedy strategy. However, this is not always optimal, as the following example shows: (The first player would win if she would first pick the 3 instead of the 4.)
3 2 10 4
You are to determine exactly how bad the greedy strategy is for different games when the second player uses it but the first player is free to use any strategy she wishes.
Input
There will be multiple test cases. Each test case will be contained on one line. Each line will start with an even integer n followed by n positive integers. A value of n = 0 indicates end of input. You may assume that n is no more than 1000. Furthermore, you may assume that the sum of the numbers in the list does not exceed 1,000,000.
Output
For each test case you should print one line of output of the form:
  In game m, the greedy strategy might lose by as many as p points.
where m is the number of the game (starting at game 1) and p is the maximum possible difference between the first player‘s score and second player‘s score when the second player uses the greedy strategy. When employing the greedy strategy, always take the larger end. If there is a tie, remove the left end.

题意:给定一个数列,两人轮流取数,只能从两端取,第一个取的人可以用任何策略,第二个贪心,问结束时第一个人会赢多少分。

思路就是Top-Down的动态规划+记忆化搜索或者Bottom-Up的动态规划,,复杂度O(n2)。由于有比较多的判断就不写状态转移方程了,具体见代码和注释。

Notes:

Top-Down DP + Memorization 与 Bottom-Up DP 的区别

两种写法:

1. Top-Down:

//#define JDEBUG

#include<cstdio>
#include<cstring>
#include<algorithm>

int cards[1001];
int state[1001][1001];

/**
 * Top-Down DP. Get the scores won by a in [l, r]
 *
 * @param l   start of the interval
 * @param r   end of the interval
 * @return  the scores won by a in [l, r]
 */
int dp(int l, int r) {
    // reach the end
    if (l > r)
        return 0;
    // one card
    if (l == r)
        return cards[l];
    // [Memoization] searched
    if (state[l][r] != -1)
        return state[l][r];

    int takeLeft = 0, takeRight = 0;

    // check what happens if a takes left
    // cards[r] > cards[l+1], so b would take right
    // narrowdown to [l+1, r-1]
    if (cards[r] > cards[l + 1]) {
        takeLeft = dp(l + 1, r - 1) + cards[l];
    } else {  // cards[r] <= cards[l+1], so b would take next left
    // narrow down to [l+2, r]
        takeLeft = dp(l + 2, r) + cards[l];
    }

    // check what happens if a takes right
    // cards[r-1] > cards[l], so b would take next right
    // narrow down to [l, r-2]
    if (cards[r - 1] > cards[l]) {
        takeRight = dp(l, r - 2) + cards[r];
    } else {  // cards[r-1] <= cards[l], so b would take left
    // narrow down to [l+1, r-1]
        takeRight = dp(l + 1, r - 1) + cards[r];
    }

    // return the best outcome
    return state[l][r] = (takeLeft > takeRight) ? takeLeft : takeRight;
}

int main(void) {
#ifdef JDEBUG
    freopen("1176.in", "r", stdin);
    freopen("1176.out", "w", stdout);
#endif

    int n = 0;
    int game = 1;
    while(scanf("%d", &n) && n != 0) {
        // initialization
        int sum = 0;
        memset(cards, -1, sizeof(cards));
        memset(state, -1, sizeof(state));

        for(int i = 0; i < n; i++) {
            scanf("%d", &cards[i]);
            sum += cards[i];
        }

        int scoreOfA = dp(0, n - 1);
        int scoreOfB = sum - scoreOfA;
        printf("In game %d, the greedy strategy might lose by as many as %d points.\n",
            game++, scoreOfA - scoreOfB);
    }
}

2. Bottom-Up

//#define JDEBUG
#include<cstdio>
#include<cstdlib>
#include<cstring>

int cards[1001];
int state[1001][1001];

/**
 * Bottom up DP.
 *
 * @param  n number of cards
 * @return   score by which b will lose
 */
int dp(int n) {
    // base case: in [i, i+1], a would take the larger one,
    // so b lose by abs(cards[i] - cards[i + 1])
    for (int i = 0; i < n - 1; i++) {
        state[i][i + 1] = abs(cards[i] - cards[i + 1]);
    }

    // dp starts from [l, l+3] since [l, l+1] is known
    // iterate: when [l, l+intvl] are left
    for (int intvl = 3; intvl < n; intvl++) {
        for (int l = 0; l < n - intvl; l++) {
            int r = l + intvl;
            int takeLeft = 0, takeRight = 0;

            // check what happens if a takes left
            // cards[r] > cards[l+1], so b would take right
            if (cards[r] > cards[l + 1]) {
                takeLeft = state[l + 1][r - 1] + cards[l] - cards[r];
            } else {  // cards[r] <= cards[l+1], so b would take next left
                takeLeft = state[l + 2][r] + cards[l] - cards[l + 1];
            }

            // check what happens if a takes right
            // cards[r-1] > cards[l], so b would take next right
            if (cards[r - 1] > cards[l]) {
                takeRight = state[l][r - 2] + cards[r] - cards[r - 1];
            } else {  // cards[r-1] <= cards[l], so b would take left
                takeRight = state[l + 1][r - 1] + cards[r] - cards[l];
            }

            // use the one with the best outcome
            state[l][r] = takeLeft > takeRight ? takeLeft : takeRight;
        }
    }

    return state[0][n - 1];
}

int main(void) {
#ifdef JDEBUG
    freopen("1176.in", "r", stdin);
    freopen("1176.out", "w", stdout);
#endif
    int n = 0;
    int game = 1;

    while (scanf("%d", &n) && n != 0) {
        // store the card numbers
        for (int i = 0; i < n; i++) {
            scanf("%d", &cards[i]);
        }

        memset(state, 0, sizeof(state));
        printf("In game %d, the greedy strategy might lose by as many as %d points.\n",
               game++, dp(n));
    }

    return 0;
}
时间: 2024-08-04 12:18:41

sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)的相关文章

Codevs_1017_乘积最大_(划分型动态规划/记忆化搜索)

描述 http://codevs.cn/problem/1017/ 给出一个n位数,在数字中间添加k个乘号,使得最终的乘积最大. 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友

动态规划①——记忆化搜索

首先的首先,必须明白动态规划(DP)以后很有用很有用很有用很有用……首先的其次,必须明白:动规≍搜索=枚举 一.最简单的记忆化搜索(应该可以算DP) 题目(来自洛谷OJ)http://www.luogu.org/problem/show?pid=1434# [不麻烦大家自己找了]题目描述 DescriptionMichael喜欢滑雪.这并不奇怪,因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道在一个区域中最

UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)

描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=378 n种方块,给出每一种的长宽高,现在要落起来,上面的方块的长和宽要严格小于下面的方块,问最多落多高. ACM Contest Problems ArchiveUniversity of Valladolid (SPAIN)437 The Tower of BabylonPerhap

动态规划-记忆化搜索

1.数字三角形 学习链接:http://blog.csdn.net/zwhlxl/article/details/46225947 输入样例: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 输出样例: 30 递归代码: #include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <

着色方案(动态规划+记忆化搜索)

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1079 AC代码: 1 /* 2 直接状态压缩是显然是不可行的,我们考虑如果没有相邻颜色不相同的限制的话, 3 如果两种油漆能染的木块数目相同,我们就可以认为两种油漆无差别. 4 设dp[a1][a2][a3][a4][a5]为能染1个木块的油漆有a1种……的方案数. 5 但是有相邻颜色的限制,如果上一次用了颜色数为k的油漆, 6 那么这一次有一种颜色数为k-1的油漆就不能用了,转移的时

[hdoj]1244记忆化搜索

题解参考:http://www.cnblogs.com/peaceful-andy/archive/2012/08/14/2638907.html 很久很久以前……我一直以为记忆化搜索就是dp,dp就是记忆化搜索……多么悲哀的认识…… 动态规划是“填表格”的顺序依次递推,记忆化搜索说白了就是搜索的一种,树型,二者的相同点就是,边运行边记忆,对于计算过的都存起来,不再重复计算. 1 #include <iostream> 2 using namespace std; 3 4 const int

sicily 1219(记忆化搜索)

题目链接:sicily 1214 解题思路: 博弈题,用搜索来做.但是,如果用普通的搜索来做的话,是会超时的--复杂度大约是O( n^n ),所以需要采用记忆化搜索的方法(其实差不多就是动态规划了,但是这里是树形DP). 状态: 用集合S表示现在树的状态,i 表示现在轮到谁进行砍边,dp[ S ][ i ]表示最优值.集合S可以用二进制来表示,即001表示现在还剩下第0条边. 状态转移: 1)A的目标是取最大值,B的目标是取最小值,我们在推导当前状态的最优解时,需要分两种情况考虑!即A得维护较大

算法导论学习-动态规划之记忆化搜索

一. 动态规划 动态规划(dynamic programming),与“分治思想”有些相似,都是利用将问题分 为子问题,并通过合并子问题的解来获得整个问题的解.于“分治”的不同之处在 于,对于一个相同的子问题动态规划算法不会计算第二次,其实现原理是将每一个计算过的子问题的值保存在一个表中. 二. 记忆化搜索 我们常见的动态规划问题,比如流水线调度问题,矩阵链乘问题等等都是“一步接着一步解决的”,即规模为 i 的问题需要基于规模 i-1 的问题进行最优解选择,通常的递归模式为DP(i)=optim

集训第五周动态规划 I题 记忆化搜索

Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.在上面的例子