zoukankan      html  css  js  c++  java
  • hdu 4579 博弈+区间dp

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int maxe = 50000;
    const int maxn = 26;
    const int INF  = 0x3f3f3f;
    
    int dp[maxn][maxn][maxn][maxn];  //dp[l1][r1][l2][r2] 表示先手与后手取得到的最大差值。
    bool vis[maxn][maxn][maxn][maxn];
    int a[maxn],b[maxn];
    int N;
    
    int dfs(int l1,int r1,int l2,int r2){
        if(vis[l1][r1][l2][r2])  return dp[l1][r1][l2][r2];
        vis[l1][r1][l2][r2] = true;
     
        if(l1>r1 && l2>r2)  return dp[l1][r1][l2][r2] = 0;  //这地方必须这样写,不能只写成return 0;
        int ans = -INF;
    
        if(l1 <= r1){
            ans = max(ans,a[l1] - dfs(l1+1,r1,l2,r2));  //dfs(l1+1,r1,l2,r2)表示你先手走了以后,别人作为先手得到的最大差值。所以应该用a[l1]-dfs()表示你作为先手的最大值。
            ans = max(ans,a[r1] - dfs(l1,r1-1,l2,r2));
        }
        if(l2 <= r2){  
            ans = max(ans,b[l2] - dfs(l1,r1,l2+1,r2));
            ans = max(ans,b[r2] - dfs(l1,r1,l2,r2-1));
        }
        return dp[l1][r1][l2][r2] = ans;
    }
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
        int T;
        cin>>T;
        while(T--){
            cin>>N;
            memset(dp,-0x3f,sizeof(dp));
            memset(vis,0,sizeof(vis));
            int tot = 0;
            for(int i=1;i<=N;i++)    scanf("%d",&a[i]), tot += a[i];
            for(int i=1;i<=N;i++)    scanf("%d",&b[i]), tot += b[i];
    
            dfs(1,N,1,N);
            cout<<(dp[1][N][1][N]+tot)/2<<endl;
        }
    }
    View Code

    下面是参考别人例外一种好的思路:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int maxe = 50000;
    const int maxn = 26;
    const int INF  = 0x3f3f3f;
    
    int dp[maxn][maxn][maxn][maxn];  //dp[l1][r1][l2][r2] 表示先手取得到的最大值。
    int a[maxn],b[maxn];
    int sum1[maxn],sum2[maxn];
    int N;
    
    int dfs(int l1,int r1,int l2,int r2){
        if(dp[l1][r1][l2][r2] != -1 )     return dp[l1][r1][l2][r2]  ;
        if(l1>r1 && l2>r2)  return 0;
        int ans = 0;
        int sum = 0;
        if(l1 <= r1)  sum += sum1[r1] - sum1[l1-1];
        if(l2 <= r2)  sum += sum2[r2] - sum2[l2-1];
    
        if(l1 <= r1){
            ans = max(ans,sum-dfs(l1+1,r1,l2,r2));  //避免了直接用dp[l1][r1][l2][r2];
            ans = max(ans,sum-dfs(l1,r1-1,l2,r2));
        }
        if(l2 <= r2){
            ans = max(ans,sum-dfs(l1,r1,l2+1,r2));
            ans = max(ans,sum-dfs(l1,r1,l2,r2-1));
        }
        return dp[l1][r1][l2][r2] = ans;
    }
    int main()
    {
        //freopen("E:\acm\input.txt","r",stdin);
        int T;
        cin>>T;
        while(T--){
            cin>>N;
            memset(dp,-1,sizeof(dp));
            sum1[0] = 0;  sum2[0] = 0;
            for(int i=1;i<=N;i++)    scanf("%d",&a[i]), sum1[i] = sum1[i-1] + a[i];
            for(int i=1;i<=N;i++)    scanf("%d",&b[i]), sum2[i] = sum2[i-1] + b[i];
    
            cout<<dfs(1,N,1,N)<<endl;
        }
    }
    View Code
  • 相关阅读:
    网站的安全架构
    Charles Proxy for Mac & Windows (4.1.3)破解激活工具
    charles抓包工具的中文乱码解决方法
    Charles 从入门到精通
    go语言知识点
    Golang Import使用入门
    算法图解之选择排序
    算法图解之数组和链表
    算法图解之大O表示法
    算法图解之内存的工作原理
  • 原文地址:https://www.cnblogs.com/acmdeweilai/p/3280325.html
Copyright © 2011-2022 走看看