数组两边轮流取数,求谁和大

题目描述:

  • 有一个数组,A和B竞赛,规则是:A先取数组两端中的一个数,然后B在剩下的数组两端取一个数,然后A取,B取…,直至数组取完,假如A中所有数之和>=B,则输出true,否则输出false。

动态规划递推公式:

  • 设 f[m][n],表示数组num[m]-num[n]间,A的积分 - B的积分
  • //A取左边
  • temp1 = min(num[m]-num[m+1]+f[m+2][n], num[m]-num[n]+f[m+1][n-1])
  • //A取右边
  • temp2 =min(num[n]-num[m]+f[m+1][n-1], num[n]-num[n-1]+f[m][n-2])
  • f[m][n]=max(temp1,temp2)

计算方向:

  • f[m][n]与f[m+2][n]、f[m+1][n-1]、f[m][n-2],即与矩阵上左、下、左下有关,则计算方向为,矩阵上正对角,向右计算
  • 初始化: f[m][n]=num[m] m==n
  • f[m][n]=abs(num[m][n]) m+1==n

代码:

#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;

int main(){
    long num[20];
    long dp[20][20];
    int length = 0;

    while(scanf("%d", &num[length])!=EOF){
        length++;
    }
    // 初始化
    for(int j=0;j<length;j++){
        for(int l=0;l<length;l++)
            dp[j][l]=0;
    }

    int len=0;
    //  偶数
    if(length%2==0){
        for(int j=0;j<length-1;j++)
            dp[j][j+1]=abs(num[j]-num[j+1]);
        len = 3;
    }else{
        for(int j=0;j<length;j++)
            dp[j][j]=num[j];
        len =2;
    }

    int index = len;
    //index开始,计算dp向后递归
    for(int k =index;k<length;k+=2){
        for(int t = 0;t<length-k;t++){
            dp[t][t+len]=max(min(num[t]-num[t+1]+dp[t+2][t+len], num[t]-num[t+len]+dp[t+1][t+len-1]),
                             min(num[t+len]-num[t]+dp[t+1][t+len-1], num[t+len]-num[t+len-1]+dp[t][t+len-2]));
        }
        len+=2;
    }
    printf("The DP matrix is:\n");
    for(int k =0;k<length;k++){
        for(int t = 0;t<length;t++){
             printf("%d ",dp[k][t]);
        }
        printf("\n");
    }

    if(dp[0][length-1]>=0)
        printf("true\n");
    else
        printf("false\n");

    return 0;
}

结果:(linux 下 输入EOF结束符 ctrl+shift+D)
5 2 13 20 6 2
The DP matrix is:
0 3 0 10 0 6
0 0 11 0 3 0
0 0 0 7 0 3
0 0 0 0 14 0
0 0 0 0 0 4
0 0 0 0 0 0
true

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值