有n枚硬币按照0到n-1对它们进行编号,其中编号为i的硬币面额为vi,两个人轮流从剩下硬币中取出一枚硬币归自己所有,但每次取硬币的时候只能取剩下的硬币中编号最小的硬币或者编号最大的硬币,在两个都采用最

该问题是一个动态规划问题
二人的最佳选择都是选择当前值加上之后选择值的和最大的情况
我们用maxValue[i][j]表示在剩余硬币为i~j的时候,二人可以拿到的最大和值;用select[i][j]表示在在剩余硬币为i~j的时候,选择的硬币标号。
当只剩1个硬币的时候: maxValue[i][i] = v[i] 
当只剩2个硬币的时候: maxValue[i][j] = max(v[i], v[i + 1])
当剩余硬币大于等于3个时,需要知道自己拿完后另一个人的策略:
1.当自己拿的是编号最小的硬币:
        1.另一个人拿的是编号最大的硬币,自己之后可以拿到的最大和值为:first = v[i] + maxValue[i + 1][j - 1];
        2.另一个人拿的也是编号最小的硬币,自己之后可以拿到的最大和值为:first = v[i] + maxValue[i + 2][j];
2.当自己拿的是编号最大的硬币:
        1.另一个人拿的是编号最小的硬币,自己之后可以拿到的最大和值为:last = maxValue[i + 1][j - 1] + v[j];
        2.另一个人拿的也是编号最大的硬币,自己之后可以拿到的最大和值为:last = maxValue[i][j - 2] + v[j];
所以,这时自己应该拿到的最大和值尾max(first, last)。


#include<stdio.h>
#include<memory.h>
#define N 100
intv[N];
intmaxValue[N][N];
intselect[N][N];
intMaxValue(intv[],intn);
intmain(){
    intn;
    while(EOF != scanf("%d", &n)){
        for(inti = 0; i < n; i++){
            scanf("%d", &v[i]);
        }
        printf("%d", MaxValue(v, n));
    }
}
intMaxValue(intv[], intn){
    inti, j, len;
    for(i = 0; i < n; i++)
        maxValue[i][i] = v[i];
        select[i][i] = i;
    for(i = 0; i < n - 1; i++){
        if(v[i] > v[i + 1]){
            maxValue[i][i + 1] = v[i];
            select[i][i + 1] = i;
        }
        else{
            maxValue[i][i + 1] = v[i + 1];
            select[i][i + 1] = i + 1;
        }
    }
    for(len = 3; len <= n; len++){
        for(i = 0; i < n - len + 1; i++){
            j = i + len - 1;
            intfirst, last;
            if(select[i + 1][j] == j)
                first = v[i] + maxValue[i + 1][j - 1];
            elseif(select[i + 1][j] == i + 1)
                first = v[i] + maxValue[i + 2][j];
            if(select[i][j - 1] == i)
                last = maxValue[i + 1][j - 1] + v[j];
            elseif(select[i][j - 1] == j - 1)
                last = maxValue[i][j - 2] + v[j];
            if(first > last){
                maxValue[i][j] = first;
                select[i][j] = i;
            }
            else{
                maxValue[i][j] = last;
                select[i][j] = j;
            }
        }
    }
    returnmaxValue[0][n - 1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值