zoukankan      html  css  js  c++  java
  • Acwing-283-多边形(区间DP)

    链接:

    https://www.acwing.com/problem/content/285/

    题意:

    “多边形游戏”是一款单人益智游戏。

    游戏开始时,给定玩家一个具有N个顶点N条边(编号1-N)的多边形,如图1所示,其中N = 4。

    每个顶点上写有一个整数,每个边上标有一个运算符+(加号)或运算符*(乘号)。

    1179_1.jpg

    第一步,玩家选择一条边,将它删除。

    接下来在进行N-1步,在每一步中,玩家选择一条边,把这条边以及该边连接的两个顶点用一个新的顶点代替,新顶点上的整数值等于删去的两个顶点上的数按照删去的边上标有的符号进行计算得到的结果。

    下面是用图1给出的四边形进行游戏的全过程。

    1179_2.jpg

    最终,游戏仅剩一个顶点,顶点上的数值就是玩家的得分,上图玩家得分为0。

    请计算对于给定的N边形,玩家最高能获得多少分,以及第一步有哪些策略可以使玩家获得最高得分。

    思路:

    先处理环, 将环变成链式再扩大两倍,就可以处理环了,从l-(l+n-1)的范围就是将l前面的边在第一步断开的情况.
    考虑步数, 对两个堆进行dp, 操作受到符号限制.

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 1e9;
    const int NINF = -1e9;
    
    int a[110], op[110];
    int Dp[110][110][2];
    int n;
    char ope;
    
    int main()
    {
        scanf("%d", &n);
        getchar();
        for (int i = 1;i <= n;i++)
        {
            scanf("%c%d", &ope, &a[i]);
            getchar();
    //        cout << ope << endl;
            if (ope == 't')
                op[i] = 1;
            else
                op[i] = 0;
        }
        for (int i = n+1;i <= 2*n;i++)
        {
            a[i] = a[i-n];
            op[i] = op[i-n];
        }
        for (int i = 1;i <= 2*n;i++)
        {
            for (int j = 1;j <= 2*n;j++)
            {
                Dp[i][j][0] = NINF, Dp[i][j][1] = INF;
                if (i == j)
                    Dp[i][j][0] = Dp[i][j][1] = a[i];
            }
        }
    //    for (int i = 1;i <= 2*n;i++)
    //        cout << op[i] << ' ' << a[i] << ' ' ;
    //    cout << endl;
        for (int len = 2;len <= n;len++)
        {
            for (int l = 1;l <= 2*n-len+1;l++)
            {
                int r = l+len-1;
                for (int k = l;k < r;k++)
                {
                    if (op[k+1] == 1)
                    {
                        Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][0]+Dp[k+1][r][0]);
                        Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][1]+Dp[k+1][r][1]);
                    }
                    else
                    {
                        Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][0]*Dp[k+1][r][0]);
    //                    Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][0]+Dp[k+1][r][0]);
                        Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][1]*Dp[k+1][r][1]);
                        Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][1]*Dp[k+1][r][0]);
                        Dp[l][r][0] = max(Dp[l][r][0], Dp[l][k][0]*Dp[k+1][r][1]);
    
                        Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][1]*Dp[k+1][r][1]);
    //                    Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][1]+Dp[k+1][r][1]);
                        Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][0]*Dp[k+1][r][0]);
                        Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][1]*Dp[k+1][r][0]);
                        Dp[l][r][1] = min(Dp[l][r][1], Dp[l][k][0]*Dp[k+1][r][1]);
                    }
                }
            }
        }
        int ans = NINF;
        for (int l = 1;l <= n+1;l++)
        {
            int r = l+n-1;
    //        cout << Dp[l][r][0] << endl;
            ans = max(ans, Dp[l][r][0]);
        }
        set<int> st;
        for (int l = 1;l <= n;l++)
        {
            int r = l+n-1;
            if (Dp[l][r][0] == ans)
                st.insert(l);
        }
        printf("%d
    ", ans);
        for (auto x: st)
            printf("%d ", x);
        puts("");
    
        return 0;
    }
    /*
    3
    t 1 t 1 x 1
     */
    
  • 相关阅读:
    Angular 项目打包之后,部署到服务器,刷新访问404解决方法
    C# yield return; yield break;
    C#获取枚举描述
    21、uwp UI自动化测试(WinAppDriver)
    20、uwp打包失败(All app package manifests in a bundle must declare the same values under the XPath *[local-name()='Package']/*[local-name()='Dependencies'])
    19、UWP 新特性(Creator Update)
    18、利用 Windows Device Portal 获取用户闪退 dump
    17、uwp 打包失败记录
    爱奇艺招聘uwp开发
    16、C++获取磁盘空间的方法
  • 原文地址:https://www.cnblogs.com/YDDDD/p/11509513.html
Copyright © 2011-2022 走看看