题目描述:
- 有一个数组,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