zoukankan      html  css  js  c++  java
  • sum游戏 Game of sum uva 10891 动态规划 备忘录(记忆化搜索)

    题目的大意是有一个整数组成的序列,两个人轮流取数,只能从一端取一个或者多个数(这里大白书上写错了),当所有的数都被取完的时候,取到的所有的数之和为该玩家的分数,求A的分数-B的分数,两个人都是以最优的方案取值。这个问题使用动态规划求解,子问题就是i~j的子序列先手取得的分数最大值。

    设d[i][j]表示子序列i~j的先手取数所获得的最大分数则d[i][j]=sum[i][j]-min(d[i+1][j],d[i+2][j],d[i+3][j],...,d[j][j],....,d[i][j-1],d[i][j-2],d[i][j-3],...,d[i][i],0)。0表示所有的数都被先手取完。因此最后的计算结果就是d[1][n]-(sum[1][n]-d[i][n])即是2*d[1][n]-sum[1][n]。动态规划使用备忘录方法。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAXN 200
    #define INF 1000000000
    int s[MAXN];
    int n;
    int d[MAXN][MAXN];
    int sum[MAXN];
    int dp(int i,int j)
    {
    	if(d[i][j]!=INF)return d[i][j];
    	if(i==j)return sum[i]-sum[i-1];
    	int t=0;
            for(int ii=i+1;ii<=j;ii++)
    		t=min(t,dp(ii,j));
    	for(int jj=j-1;jj>=i;jj--)
    		t=min(t,dp(i,jj));
    	d[i][j]=sum[j]-sum[i-1]-t;
    	return d[i][j];
    }
    int main()
    {
    	while(scanf("%d",&n),n)
    	{
    		sum[0]=0;
    		for(int i=0;i<MAXN;i++)
    			for(int j=0;j<MAXN;j++)d[i][j]=INF;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d",&s[i]);
    			sum[i]=sum[i-1]+s[i];
    		}
                    cout<<dp(1,n)*2-sum[n]<<endl;
            }
    
    }
    


     

  • 相关阅读:
    fianl关键字和static关键字
    jdk的安装
    this关键字和super关键字
    Java 数组
    网络通信知识复习
    Linux 下执行本目录的可执行文件(命令)为什么需要在文件名前加“./”
    CentOS 7 下安装 teamviewer 13
    我的 Putty 配色方案
    在 Mac OS X 下,如何向 sudoers 文件添加新用户
    Windows 7 下使用 pandoc 转换文档格式
  • 原文地址:https://www.cnblogs.com/jackwuyongxing/p/3366474.html
Copyright © 2011-2022 走看看