首页 > 其他分享 >洛谷题单指南-动态规划3-P4342 [IOI1998] Polygon

洛谷题单指南-动态规划3-P4342 [IOI1998] Polygon

时间:2024-05-15 12:42:05浏览次数:15  
标签:分数 Polygon min int 洛谷题 最大值 P4342 max 节点

原题链接:https://www.luogu.com.cn/problem/P4342

题意解读:环中节点表示数字,边表示运算符,可以任意断一条边,其余节点两两按边的符号计算,求结果的最大值,以及最大值是断开那些边可以得到。

解题思路:

题意中有几个个关键信息:

  • 环形,节点数为n,边数为n
  • 任意断一条边,即可以从任意节点开始,进行区间长度为n个节点的合并操作

本质上就是一个环形dp问题,因此可以将原节点、边拉平并放大两倍长度,再枚举每一个长度1 ~ n的区间进行dp操作

1、状态表示

设s[i]为第i个符号,设a[i]为第i个数字, a[i]和a[i+1]通过符号s[i+1]相连

设f[i][j]表示从i ~ j之间可求出的最高分数

设g[i][j]表示从i ~ j之间可求出的最低分数

为什么需要最低分数?因为在计算中有乘法,且有负数存在,可能出现最低分数*最低分数得到最高分数的情况,因此要计算最高分数,需要依赖之前的最高、最低两种分数。

2、状态转移

设最后一次合并分界点在k,也就是i~k已合并,k+1~j也已合并,要计算f[i][j]

如果s[k+1]是加号t:

  f[i][j] = max(f[i][j], f[i][k] + f[k+1][j]);

  g[i][j] =min(g[i][j], g[i][k] +g[k+1][j]);

如果s[k+1]是乘号x:

  由于有正负的差异,所以i~j最大值的计算有四种可能:

  i~k的最大值 * k+1~j的最大值、i~k的最大值 * k+1~j的最小值、i~k的最小值 * k+1~j的最大值、i~k的最小值 * k+1~j的最小值

  以上四种取max即可

  f[i][j] = max(f[i][j], f[i][k] * f[k+1][j])

  f[i][j] = max(f[i][j], f[i][k] *g[k+1][j])

  f[i][j] = max(f[i][j], g[i][k] *f[k+1][j])

  f[i][j] = max(f[i][j], g[i][k] *g[k+1][j])

  同样的道理,i~j最小值的计算也有四种可能,直接给出递推式:

  g[i][j] = min(g[i][j], g[i][k] * g[k+1][j])

  g[i][j] = min(g[i][j], g[i][k] *f[k+1][j])

  g[i][j] = min(g[i][j], f[i][k] *g[k+1][j])

  g[i][j] = min(g[i][j], f[i][k] *f[k+1][j])

3、初始化

f初始化为极小值,g初始化为极大值,对于len=1的区间f[i][i] = g[i][i] = a[i]

4、结果

所有f[i][i+n-1]的最大值

要看具体断开那条边,即为满足f[i][i+n-1]等于最大值是的i值。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 105; //放大两倍,环形dp问题
const int INF = 0x3f3f3f3f;

int n;
char s[N]; //符号
int a[N]; //数字,a[i]和a[i+1]通过符号s[i+1]相连
int f[N][N]; //f[i][j]表示从i ~ j之间可求出的最高分数
int g[N][N]; //g[i][j]表示从i ~ j之间可求出的最低分数
int ans = -INF; //要计算最大值,有负数存在,因此初始化为极小值

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> s[i] >> a[i];
        s[i + n] = s[i]; //两倍长度
        a[i + n] = a[i]; //两倍长度
    }

    for(int i = 1; i <= 2 * n; i++)
    {
        for(int j = 1; j <= 2 * n; j++)
        {
            f[i][j] = -INF;     
            g[i][j] = INF;
        }
    }         

    for(int len = 1; len <= n; len++) //枚举区间长度
    {
        for(int i = 1; i + len - 1 <= 2 * n; i++) //枚举左端点
        {
            int j = i + len - 1; //计算右端点
            if(len == 1) f[i][j] = g[i][j] = a[i]; //区间长度为1,合并结果是自身数值
            else 
            {
                for(int k = i; k < j; k++) //枚举最后一次合并的分界点,i~k、k+1~j都已合并完
                {
                    if(s[k+1] == 't')
                    {
                        f[i][j] = max(f[i][j], f[i][k] + f[k+1][j]);
                        g[i][j] = min(g[i][j], g[i][k] + g[k+1][j]);
                    }
                    if(s[k+1] == 'x') 
                    {
                        f[i][j] = max(f[i][j], f[i][k] * f[k+1][j]);
                        f[i][j] = max(f[i][j], f[i][k] * g[k+1][j]);
                        f[i][j] = max(f[i][j], g[i][k] * f[k+1][j]);
                        f[i][j] = max(f[i][j], g[i][k] * g[k+1][j]);
                        g[i][j] = min(g[i][j], g[i][k] * g[k+1][j]);
                        g[i][j] = min(g[i][j], g[i][k] * f[k+1][j]);
                        g[i][j] = min(g[i][j], f[i][k] * g[k+1][j]);
                        g[i][j] = min(g[i][j], f[i][k] * f[k+1][j]);
                    }
                }
            }
        }
    }

    for(int i = 1; i <= n; i++) ans = max(ans, f[i][i+n-1]);
    cout << ans << endl;
    for(int i = 1; i <= n; i++)
    {
        if(f[i][i+n-1] == ans)
        {
            cout << i << " "; //断开边的编号即同起始点的位置
        }
    }

    return 0;
}

 

标签:分数,Polygon,min,int,洛谷题,最大值,P4342,max,节点
From: https://www.cnblogs.com/jcwy/p/18193603

相关文章

  • 洛谷题单指南-动态规划3-P1070 [NOIP2009 普及组] 道路游戏
    原题链接:https://www.luogu.com.cn/problem/P1070题意解读:1~n个环形机器人工厂,相邻工厂之间的道路是1~n,每个时刻可以从任意工厂购买机器人,走不超过p时间,不同工厂购买机器人花费不同的金币,不同时刻走到不同道路也能得到不同的金币,问一共m时间,最多可以得到多少金币(需减去购买机器人......
  • 洛谷题单指南-动态规划3-P1063 [NOIP2006 提高组] 能量项链
    原题链接:https://www.luogu.com.cn/problem/P1063题意解读:本质上是一个环形石子合并问题,计算合并产生的最大能量。解题思路:对于环形DP问题,可以把环拆开,并复制2倍长度,然后用1~n的区间长度去枚举1、状态表示设structnode{inthead,tail}用于表示每一个项链节点,其中有头、尾......
  • 洛谷题单指南-动态规划3-P4170 [CQOI2007] 涂色
    原题链接:https://www.luogu.com.cn/problem/P4170题意解读:长度为n的字符串,每次可以将连续一段填为同一个字符,求要填成目标串的最少填涂次数。解题思路:1、状态表示:设s表示目标字符串,dp[i][j]表示将i~j涂成目标"颜色"的最少次数2、状态转移考虑i~j的两端,当i==j,说明只有一个......
  • 洛谷题单指南-动态规划3-P1140 相似基因
    原题链接:https://www.luogu.com.cn/problem/P1140题意解读:两个只包含A、C、G、T4个字符的序列,根据已经定义好的字符-字符的相似度,计算两个序列最大的相似度,两个序列必须每个字符都配对,如果字符不够,可以插入'-'代替。解题思路:本题要解决几个问题:1、状态表示既然有两个序列,设......
  • 洛谷题单指南-动态规划3-P1880 [NOI1995] 石子合并
    原题链接:https://www.luogu.com.cn/problem/P1880题意解读:计算n堆石子合并的最小、最大得分,只不过这n堆石子是环形的,也就是首、尾也相邻,是区间DP的升级版-环形DP问题。解题思路:如果是常规区间DP的方法:对于n堆石子,考察区间的长度范围是1~n先枚举左端点i,范围是1~n再计算右......
  • 洛谷题单指南-动态规划3-P3205 [HNOI2010] 合唱队
    原题链接:https://www.luogu.com.cn/problem/P3205题意解读:给定理想队形,计算初始队形的方案数。解题思路:对于给定理想队形,最后一个人插入有两种可能:从左边插入、从右边插入从左边插入,则意味着前一个数比当前数大,前一个数有可能在左边也有可能在右边从右边插入,则意味着前一个数......
  • 洛谷题单指南-动态规划3-Zuma
    原题链接:https://www.luogu.com.cn/problem/CF607B题意解读:从一组整数中取连续的回文子串,求最少几次可以取完。解题思路:状态表示:设dp[i][j]表示取i~j之间的回文子串所需的最少次数,a[i]表示第i个数状态转移:如果a[i]==a[j],dp[i][j]=dp[i+1][j-1],因为首尾如果相等,其必然可以......
  • luogu P4342[IOI1998]Polygon
    阅读前需深剖析分系列是记录我个人的做题思路,实现过程的全面分析,存在内容可靠、思路健全、分析到位、试错纠错等优于一般题解的特征,其中,Quest部分表示探索问题,我会在此提出做题时的想法、问题,并在内容中得到解决,因此建议从上到下按序浏览,以防出现思路断层,内容不衔接的情况,感谢理......
  • 洛谷题单指南-动态规划3-P1775 石子合并(弱化版)
    原题链接:https://www.luogu.com.cn/problem/P1775题意解读:计算合并石子的最小代价,区间DP。解题思路:状态表示:dp[i][j]表示将第i~j堆石子合并的最小代价,m[i]表示第i堆石子质量,s[i]表示前i堆石子质量前缀和状态转移:考虑最后一次合并,设最后一次合并是将i~k合成的一堆与k+1~j合成......
  • 洛谷题单指南-动态规划2-P3147 [USACO16OPEN] 262144 P
    原题链接:https://www.luogu.com.cn/problem/P3147题意解读:将一组数据两两相邻且相同的合并,合并成一个数值+1的数,求合并后的最大值。解题思路:考虑合并后的最大数i,其最后一次必然是由两个i-1合并而来的设dp[i][j]表示以j为左端点,合并最大值为i时的右端点的下一个位置如图:dp[i......