首页 > 试题广场 >

糖果游戏

[编程题]糖果游戏
  • 热度指数:1445 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小明和小红都很喜欢吃糖果,今天他们一起玩一个糖果游戏。他们将装有不同数量的透明糖果盒子摆放成一个环,现在两人依次选择糖果盒子,小明先拿,且小明第一次挑选可以选择环中任意一个糖果盒子,将环分割成一列有首尾的序列,之后两人每次选择时只能从剩余的糖果盒子序列的行首或者行尾挑选,直到两人将糖果盒子全部拿完,最后糖果多的为胜者。假设两人都希望自己是最后的赢家,且糖果的总数是奇数,现给定一个糖果的环,用一个数组表示环中的各糖果盒子中糖果的数量,数组首尾相连成环,元素个数为N。请输出胜利者比失败者至少多拿多少糖果。

输入描述:
第一行:N
第2至N+1行:每行一个数,代表糖果数


输出描述:
一个数,请输出胜利者比失败者多拿多少糖果
示例1

输入

4 
1
55
41
2

输出

15

说明

小明先选择55,此时环从55处断开,变为序列[41, 2, 1]
小红选择行首的41,此时剩余的序列为[2, 1]
小明选择行首的2,此时剩余的序列为[1]
小红选择剩余的1。
此时小明胜利,比小红多15个糖果
n=int(input())
nums=[]
fori inrange(n):
    tmp=int(input())
    nums.append(tmp)
defWin(num):
    n=len(num)
    dp=[[0]*n for_ inrange(n)]
    forl inrange(n):
        fori inrange(n-l):
            j=i+l
            ifl<=1: dp[i][j]=max(num[i],num[j])
            else:
                    dp[i][j]=max(min(dp[i+1][j-1],dp[i][j-2])+num[j],min(dp[i+2][j],dp[i+1][j-1])+num[i])
    return-sum(num)+2*dp[0][n-1]
 
res=0
fori inrange(n):
    index=i
    num=nums[index+1:]+nums[:index]
    res=max(res,nums[i]-Win(num))
print(res)
发表于 2019-03-13 16:53:58 回复(0)
#include <bits/stdc++.h>
using namespace std;

int F(int *a, int n){
    int dp[n][n],s=0;
    memset(dp,0,sizeof(0));
    for(int k=0;k<n;k++){
        for(int i=0;i<n-k;i++){
            int j=i+k;
            if(k<=1)
                dp[i][j] = max(a[i], a[j]);
            else
                dp[i][j] = max(min(dp[i+1][j-1], dp[i][j-2])+a[j], min(dp[i+2][j], dp[i+1][j-1])+a[i]);
        }
    }
    for(int i=0;i<n;i++)
        s += a[i];
    s = 2*dp[0][n-1]-s;
    return s;
}

int main(){
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++)
        cin>>a[i];
    
    int s = 0;
    for(int i=0;i<n;i++){
        int b[n-1],k=0;
        for(int j=i+1;j<n;j++)
            b[k++] = a[j];
        for(int j=0;j<i;j++)
            b[k++] = a[j];
        s = max(s, a[i]-F(b, n-1));
    }
    cout<<s<<endl;
    return 0;
}

发表于 2019-11-23 11:24:13 回复(0)
dic={}
def res(ary):
    if not ary:
        return 0
    if not ary in dic:
        dic[ary]=min(-res(ary[1:])-ary[0],-res(ary[:-1])-ary[-1])#对于对手来说,对手得分是负的自己得分
    return dic[ary]
a=int(input())
aa=[int(input()) for _ in range(a)]
print (abs(max([-res(tuple(aa[i:]+aa[:i])) for i in range(a)])))

发表于 2019-06-27 15:06:51 回复(0)
#include<iostream>
#include<cstring>
using namespace std;
 
#define max(a,b) (a>b?a:b)
#define abs(a) (a>0?a:-a)
int main(){
    int n;
    cin >> n;
    int dp[n+1][n+1];
    int data[n];
    for(int i=0; i<n; ++i) cin >> data[i];
    int ans = 0;
    for(int i=0; i<n; ++i) {
        memset(dp,0, sizeof(dp));
        for(int k=0; k<n; ++k)
            dp[k][k] = data[k];
        for(int k=1; k<n; ++k) {
            for(int j=0; j<n; ++j) {
              dp[j][(k+j)%n] = max(-1*dp[(j+1)%n][(k+j)%n]+data[j], -1*dp[j][(k+j-1)%n]+data[(k+j)%n]);
         //     cout << j <<"--" << (k+j)%n << ":" << dp[j][(k+j)%n] << endl;
            }
        }
        /*
        for(int k=0; k<n-1; ++k) {
            for(int j=0; j<n-1-k; ++j) {
                cout << j << "--" << k+j <<":" << dp[j][k+j] << ' ';
            }
            cout << endl;
        }
        */
    }
    for(int i=0; i<n; ++i)
        ans = max(dp[i][(i+n-1)%n], ans);
    cout << ans << endl;
    return 0;
}
//leetcode上有一题类似的,见上面链接,但本题没必要判断谁先后手,直接构造dp[i][j]表示 i-->j先手的人最大收益可得dp[i][j] = max(data[i]-dp[i+1][j], data[j]-dp[i][j-1]),由于首尾相连,加入%n即可
发表于 2019-03-23 15:20:23 回复(1)
def PredictTheWinner(nums):
    n = len(nums)
    dp = [[0] * n for _ in range(n)]
    for i in range(n):
        dp[i][i] = nums[i]
    for a in range(1,n):
        for b in range(n-a):
            i = b
            j = b+a
            dp[i][j] = max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1])
    return dp[0][-1]

nums = []
n = int(input())
for i in range(n):
    nums.append(int(input()))

maxv = -1000000
for i in range(n):
    res = nums[i+1::]+nums[0:i]
    temp = nums[i]-PredictTheWinner(res)
    if temp>maxv:
        maxv = temp
print(maxv)

发表于 2019-09-06 10:23:01 回复(0)
## 记忆化搜索写法

dfs(st, ed)表示剩[st, ed]的最大值

(1758)#include <bits/stdc++.h>
using namespace std;
 
vector<vector<int>> dp;
vector<int> nums;
int n;
 
int dfs(int st, int ed){
    if(dp[st][ed] != -1) return dp[st][ed];
    if(st == ed) return nums[st];
 
    int x = nums[st] - dfs((st-1+n)%n, ed);
    int y = nums[ed] - dfs(st, (ed+1)%n);
    int cur;
 
    cur = max(x, y);
    return dp[st][ed] = cur;
 
}
int main(){
    scanf("%d", &n);
    nums = vector<int>(n);
    for(int i=0; i<n; i++){
        scanf("%d", &nums[i]);
    }
     
   
    dp = vector<vector<int>>(n, vector<int>(n, -1));
    int maxn = 0;
    for(int i=0; i<n; i++){
        int cur = nums[i] - dfs((i-1+n)%n, (i+1)%n);
        maxn = max(cur, maxn);
    }
    cout << maxn << endl;
    return 0;
}


发表于 2020-03-07 21:28:51 回复(0)
import random
def d_candy(time,array):
    xm,xh,arr = 0,0,[]
    l_len = len(array)
    xm = random.choice(array)
    # 小明随机取第一盒糖果
    for i in range(0,l_len):
        if xm == array[i]:
            if i == 0:
                arr = array[1:]
            elif i == l_len:
                arr =array[0:l_len-2] 
            # 小明如在 [1,55,41,2,10,5,3]队首、队尾取的时候,进行的处理   
            else:
                j = i
                while j < (l_len -1):
                    j += 1
                    arr.append(array[j])
                j = 0   
                while j < i:
                    arr.append(array[j])
                    j += 1
                # 对形成的队列进行重新排序
    l_len1 = len(arr)    
    k = 0
    while l_len1 != 0:
        
        if k%2 == 0:
            r = random.choice([-1,0])
            a = arr[r]
            xh += a
            del arr[r]
            l_len1 -= 1
            k += 1
        else:
            r = random.choice([-1,0])
            b = arr[r]
            xm += b
            del arr[r]
            l_len1 -= 1
            k += 1
    if (xm - xh) > 0:
        print("小明获胜:")
        return xm - xh
    else :
        print("小红获胜:")
        return xh - xm
    
arry = []    
m = int(input())
for i in range(m):
    a = int(input())
    arry.append(a)    
print(d_candy(m,arry))
# 本地运行正常

发表于 2019-09-09 20:19:08 回复(0)