UVa 10891

来源:互联网 发布:c语言终端分屏 编辑:程序博客网 时间:2024/06/16 06:13

题目:有两个人A、B轮流在一串数字中取走一部分,每次只能从一侧取数,可以全取走但至少去一个,

            A先取,问A最大能比B大多少,两个人都很聪明。

分析:动态规划(DP),区间DP。因为数字的总和是定值,所以差值最大就是A取走的数字的和最大。

            状态定义:f(s,e)为在区间 [s, e] 上能取得的最大值;

            转移方程:f(s,e)= max(sum(s,e),lmax(s,e),rmax(s,e));

                                lmax = max( sum(s,k)+ (sum(k+1,e)- f(k+1,e)));

                                rmax= max( (sum(s,k-1)- f(s,k-1))+ sum(k,e));

说明:A在区间 [s, e] 上取走一部分是,B一定会取走剩下部分的最优解。

#include <stdio.h>#include <stdlib.h>int f[101][101];int sum[101][101];int data[101];int main(){int n;while (~scanf("%d",&n) && n) {for (int i = 1; i <= n; ++ i) {scanf("%d",&data[i]);}for (int i = 1; i <= n; ++ i) {sum[i][i] = data[i];for (int j = i+1; j <= n; ++ j) {sum[i][j] = sum[i][j-1] + data[j];}}for (int i = 1; i <= n; ++ i) {for (int j = 1; j <= n; ++ j) {f[i][j] = 0;}}//dpfor (int l = 1; l <= n; ++ l) {for (int s = 1; s+l-1 <= n; ++ s) {int e = s+l-1;f[s][e] = sum[s][e];for (int k = s; k < e; ++ k) { // leftif (f[s][e] < sum[s][e] - f[k+1][e]) {f[s][e] = sum[s][e] - f[k+1][e];}}for (int k = e; k > s; -- k) { // rightif (f[s][e] < sum[s][e] - f[s][k-1]) {f[s][e] = sum[s][e] - f[s][k-1];}}}}printf("%d\n",2*f[1][n]-sum[1][n]);}return 0;}


原创粉丝点击