zoukankan      html  css  js  c++  java
  • uva 10891 区间dp+记忆化搜索

    https://vjudge.net/problem/UVA-10891

    给定一个序列x,A和B依次取数,规则是每次只能从头或者尾部取走若干个数,A和B采取的策略使得自己取出的数尽量和最大,A是先手,求最后A-B的得分。

    令 f(i,j)表示对于[i,j]对应的序列,先手可以从中获得的最大得分,那么答案可以写为  f(i,j)-(sum(i,j)-f(i,j)),也就是 2*f(i,j)-sum(i,j)

    下面讨论f(i,j)的写法,显然递归的形式更好表达一些,为了防止重复的计算使用记忆化搜索。

    当(i==j)时显然返回a[i]即可;

    否则,我们可以枚举出所有先手可能拿走的数的区间,得出一个最大值就是返回值。

    方程就是  f(i,j)=MAX{sum(i,k)+sum(K+1,j)-f(k+1,j) , sum(k,j)+sum(i,k-1)-f(i,k-1) | i<=k<=j};  //[i,k]和[k,j]是先手可能取得区间

    还有一个转移方程是  f(i,j)=sum(i,j)-MIN(f(k1,k2)) | [k1,k2]是先手可能取得区间对应的补集。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int pre[105],a[105];
     4 int ans[105][105],vis[105][105];
     5 int sum(int i,int j)
     6 {
     7     if(i>j) return 0;
     8     return pre[j]-pre[i-1];
     9 }
    10 int f(int l,int r)
    11 {
    12     if(l>r) return 0;
    13     if(vis[l][r]) return ans[l][r];
    14     vis[l][r]=1;
    15     if(l==r) return ans[l][r]=a[l];
    16     int ret=-999999999;
    17     for(int k=l;k<=r;++k)
    18     {
    19         ret=max(ret,max(sum(l,k)+sum(k+1,r)-f(k+1,r),sum(k,r)+sum(l,k-1)-f(l,k-1)));
    20     }
    21     return ans[l][r]=ret;
    22 }
    23 int main()
    24 {
    25     int N,m,i,j,k;
    26     while(cin>>N&&N){
    27             memset(vis,0,sizeof(vis));
    28         for(i=1;i<=N;++i)
    29         {
    30             cin>>a[i];
    31             pre[i]=pre[i-1]+a[i];
    32         }
    33         cout<<2*f(1,N)-pre[N]<<endl;
    34     }
    35     return 0;
    36 }
  • 相关阅读:
    覆盖率测试工具gcov的前端工具_LCOV
    LTE切换与TAU问题
    LTE 切换过程中的数据切换
    TCP数据流稳定性--TCP分片,重组及乱序
    【Android
    【Android
    【Android
    【RN
    【RN
    【RN
  • 原文地址:https://www.cnblogs.com/zzqc/p/7339307.html
Copyright © 2011-2022 走看看