P4342 [IOI1998]Polygon —— 断链成环

这篇具有很好参考价值的文章主要介绍了P4342 [IOI1998]Polygon —— 断链成环。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4。每个顶点用整数标记,每个边用符号+(加)或符号*(乘积)标记。

P4342 [IOI1998]Polygon —— 断链成环

第一步,删除其中一条边。随后每一步:

选择一条边连接的两个顶点V1和V2,用边上的运算符计算V1和V2得到的结果来替换这两个顶点。

游戏结束时,只有一个顶点,没有多余的边。

如图所示,玩家先移除编号为3的边。之后,玩家选择计算编号为1的边,然后计算编号为4的边,最后,计算编号为2的边。结果是0。

P4342 [IOI1998]Polygon —— 断链成环

(翻译者友情提示:这里每条边的运算符旁边的数字为边的编号,不拿来计算)

编写一个程序,给定一个多边形,计算最高可能的分数。

输入格式

输入描述一个有n个顶点的多边形,它包含两行。第一行是数字n,为总边数。

第二行描述这个多边形,一共有2n个读入,每两个读入中第一个是字符,第二个是数字。

第一个字符为第一条边的计算符号(t代表相加,x代表相乘),第二个代表顶点上的数字。首尾相连。

3 < = n < = 50

对于任何一系列的操作,顶点数字都在[-32768,32767]的范围内。

输出格式

第一行,输出最高的分数。在第二行,它必须写出所有可能的被清除后的边仍能得到最高得分的列表,必须严格递增。

感谢@2016c01 提供的翻译

输入输出样例

输入 #1

4
t -7 t 4 x 2 x 5

输出 #1

33
1 2

思路

事实上,这道题,绝大多数题解都有疏漏,原因是这道题的数据是真的水。。毕竟连最小值不要都可以得到808080。。至于错误的原因在下文有说明。

让我们重新开始吧,看到这道题,我们首要的两个问题:

1.如何处理这样一个环。

2.如何得到最开始删除的边。

对于第一个问题,很轻易地就可以想到断环成链,同时我们还可以发现,通过断环成链,我们把第二个问题就解决了,我们可以通过对最后的结果再来一次对最大值的遍历,输出即可。

开始考虑DPDPDP,首先我们可以很显然的得到一个区间DPDPDP的板子:

设f[i][j]f[i][j]f[i][j]表示[i,j][i,j][i,j]这一个区间内可以得到的最大得分,转移方程如下:

加法:f[i][j]=max(f[i][k]+f[k+1][j])f[i][j]=max(f[i][k]+f[k+1][j])f[i][j]=max(f[i][k]+f[k+1][j])

乘法:f[i][j]=max(f[i][k]×f[k+1][j])f[i][j]=max(f[i][k]\times f[k+1][j])f[i][j]=max(f[i][k]×f[k+1][j])

但是我们更往深入思考,因为有乘法的存在,且有负数,那就肯定会有一个负负得正的情况,所以我们还需要维护一个最小值。设这个最小值为g[i][j]g[i][j]g[i][j]

然后就是分情况讨论的时间:

首先对于加法的情况,因为不存在负负得正一类的情况存在,所以两者的转移方程是基本一样的,大区间的最大值等于合并的两个区间的最大值之和,最小值等于合并的两个区间的最小值之和:

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

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

其次对于乘法,这里就很容易有很多遗漏点,让我们一种种分情况讨论:

(啊这里原意想画图,但考虑到手画太丑,用软件又麻烦,实在不理解可以拿着笔画一下各种情况)

1.f[i][k],g[i][k],f[k+1][j],g[k+1][j]>01.f[i][k],g[i][k],f[k+1][j],g[k+1][j] > 01.f[i][k],g[i][k],f[k+1][j],g[k+1][j]>0时:

f[i][j]=max(f[i][k]×f[k+1][j])f[i][j]=max(f[i][k]\times f[k+1][j])f[i][j]=max(f[i][k]×f[k+1][j])

g[i][j]=min(g[i][k]×g[k+1][j])g[i][j]=min(g[i][k]\times g[k+1][j])g[i][j]=min(g[i][k]×g[k+1][j])

2.f[i][k],g[i][k],f[k+1][j]>0,g[k+1][j]<02.f[i][k],g[i][k],f[k+1][j] > 0,g[k+1][j] < 02.f[i][k],g[i][k],f[k+1][j]>0,g[k+1][j]<0时:

f[i][j]=max(f[i][k]×f[k+1][j])f[i][j]=max(f[i][k]\times f[k+1][j])f[i][j]=max(f[i][k]×f[k+1][j])

g[i][j]=min(f[i][k]×g[k+1][j])g[i][j]=min(f[i][k]\times g[k+1][j])g[i][j]=min(f[i][k]×g[k+1][j])

3.f[i][k],g[i][k]>0,f[k+1][j],g[k+1][j]<03.f[i][k],g[i][k] > 0,f[k+1][j],g[k+1][j] < 03.f[i][k],g[i][k]>0,f[k+1][j],g[k+1][j]<0时:

f[i][j]=max(g[i][k]×f[k+1][j])f[i][j]=max(g[i][k]\times f[k+1][j])f[i][j]=max(g[i][k]×f[k+1][j])

g[i][j]=min(f[i][k]×g[k+1][j])g[i][j]=min(f[i][k]\times g[k+1][j])g[i][j]=min(f[i][k]×g[k+1][j])

4.f[i][k],f[k+1][j],g[k+1][j]>0,g[i][k]<04.f[i][k],f[k+1][j],g[k+1][j] > 0,g[i][k] < 04.f[i][k],f[k+1][j],g[k+1][j]>0,g[i][k]<0时:

f[i][j]=max(f[i][k]×f[k+1][j])f[i][j]=max(f[i][k]\times f[k+1][j])f[i][j]=max(f[i][k]×f[k+1][j])

g[i][j]=min(g[i][k]×f[k+1][j])g[i][j]=min(g[i][k]\times f[k+1][j])g[i][j]=min(g[i][k]×f[k+1][j])

5.f[i][k],f[k+1][j]>0,g[i][k],g[k+1][j]<05.f[i][k],f[k+1][j] > 0,g[i][k],g[k+1][j] < 05.f[i][k],f[k+1][j]>0,g[i][k],g[k+1][j]<0时:

f[i][j]=max(f[i][k]×f[k+1][j],g[i][k]×g[k+1][j])f[i][j]=max(f[i][k]\times f[k+1][j],g[i][k]\times g[k+1][j])f[i][j]=max(f[i][k]×f[k+1][j],g[i][k]×g[k+1][j])

g[i][j]=min(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j])g[i][j]=min(f[i][k]\times g[k+1][j],g[i][k]\times f[k+1][j])g[i][j]=min(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j])

(此处就没分绝对值大小的情况了,可以感性理解一下。)

6.f[i][k]>0,g[i][k],f[k+1][j],g[k+1][j]<06.f[i][k] > 0,g[i][k],f[k+1][j],g[k+1][j] < 06.f[i][k]>0,g[i][k],f[k+1][j],g[k+1][j]<0时:

f[i][j]=max(g[i][k]×g[k+1][j])f[i][j]=max(g[i][k]\times g[k+1][j])f[i][j]=max(g[i][k]×g[k+1][j])

g[i][j]=min(f[i][k]×g[k+1][j])g[i][j]=min(f[i][k]\times g[k+1][j])g[i][j]=min(f[i][k]×g[k+1][j])

7.f[k+1][j],g[k+1][j]>0,f[i][k],g[i][k]<07.f[k+1][j],g[k+1][j] > 0,f[i][k],g[i][k] < 07.f[k+1][j],g[k+1][j]>0,f[i][k],g[i][k]<0时:

f[i][j]=max(f[i][k]×g[k+1][j])f[i][j]=max(f[i][k]\times g[k+1][j])f[i][j]=max(f[i][k]×g[k+1][j])

g[i][j]=min(g[i][k]×f[k+1][j])g[i][j]=min(g[i][k]\times f[k+1][j])g[i][j]=min(g[i][k]×f[k+1][j])

8.f[k+1][j]>0,f[i][k],g[i][k],g[k+1][j]<08.f[k+1][j] > 0,f[i][k],g[i][k],g[k+1][j] < 08.f[k+1][j]>0,f[i][k],g[i][k],g[k+1][j]<0时:

f[i][j]=max(g[i][k]×g[k+1][j])f[i][j]=max(g[i][k]\times g[k+1][j])f[i][j]=max(g[i][k]×g[k+1][j])

g[i][j]=min(g[i][k]×f[k+1][j])g[i][j]=min(g[i][k]\times f[k+1][j])g[i][j]=min(g[i][k]×f[k+1][j])

9.f[i][k],g[i][k],f[k+1][j],g[k+1][j]<09.f[i][k],g[i][k],f[k+1][j],g[k+1][j] < 09.f[i][k],g[i][k],f[k+1][j],g[k+1][j]<0时:

f[i][j]=max(g[i][k]×g[k+1][j])f[i][j]=max(g[i][k]\times g[k+1][j])f[i][j]=max(g[i][k]×g[k+1][j])

g[i][j]=min(f[i][k]×f[k+1][j])g[i][j]=min(f[i][k]\times f[k+1][j])g[i][j]=min(f[i][k]×f[k+1][j])

(~~做了一个下午脑袋都要炸了,~~如果有BUGBUGBUG欢迎指出)

虽然说情况很多,但事实上你可以压成两行,不用特判。。(懒)

f[i][j]=max(f[i][j],max(f[i][k]×f[k+1][j],max(g[i][k]×g[k+1][j],max(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))f[i][j]=max(f[i][j],max(f[i][k]\times f[k+1][j],max(g[i][k]\times g[k+1][j],max(f[i][k]\times g[k+1][j],g[i][k]\times f[k+1][j]))))f[i][j]=max(f[i][j],max(f[i][k]×f[k+1][j],max(g[i][k]×g[k+1][j],max(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))

g[i][j]=min(g[i][j],min(f[i][k]×f[k+1][j],min(g[i][k]×g[k+1][j],min(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))g[i][j]=min(g[i][j],min(f[i][k]\times f[k+1][j],min(g[i][k]\times g[k+1][j],min(f[i][k]\times g[k+1][j],g[i][k]\times f[k+1][j]))))g[i][j]=min(g[i][j],min(f[i][k]×f[k+1][j],min(g[i][k]×g[k+1][j],min(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))

记得初始化长度为111的情况,至于区间端点为000的情况,由于上面的这个式子里面四种组合都全部考虑到了就可以不管了文章来源地址https://www.toymoban.com/news/detail-405137.html

代码

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

const int MAX_SIZE = 110;

#define ruan main

struct edge
{
    char c;
    int num;
};

int dp[MAX_SIZE][MAX_SIZE];
int g[MAX_SIZE][MAX_SIZE];
edge edges[MAX_SIZE];

int ruan()
{
    memset(dp, 0, sizeof(dp));
    int n;
    cin >> n;
    for(int i = 1; i <= n * 2; i++)
        for(int j = 1; j <= n * 2; j ++) {
            g[i][j] = INT_MAX;
            dp[i][j] = -INT_MAX + 1;
        }
    for(int i = 1; i <= n; i ++)
    {
        cin >> edges[i].c >> edges[i].num;
        edges[i + n] = edges[i];
        dp[i][i] = dp[i + n][i + n] = g[i + n][i + n] = g[i][i] = edges[i].num;
    }

    int maxn = -INT_MAX + 1;

    for(int j = 2; j <= n * 2; j++)
        for(int i = j - 1; i >= 1 && j - i <= n - 1; i--)
            for(int k = i; k <= j - 1; k++)
            {
                if(edges[k + 1].c == 't')
                {
                    g[i][j] = min(g[i][j], g[i][k] + g[k + 1][j]);
                    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);
                    if(j - i == n - 1)
                        maxn = max(maxn, dp[i][j]);
                }
                else
                {
                    dp[i][j]=max(dp[i][j],max(dp[i][k] * dp[k+1][j],max(g[i][k] * g[k+1][j],max(dp[i][k] * g[k+1][j],g[i][k] * dp[k+1][j]))));
                    g[i][j]=min(g[i][j],min(dp[i][k] * dp[k+1][j],min(g[i][k] * g[k+1][j],min(dp[i][k] * g[k+1][j],g[i][k] * dp[k+1][j]))));
                    if(j - i == n - 1)
                        maxn = max(maxn, dp[i][j]);
                }
            }
    cout << maxn << endl;
    for(int i = 1; i <= n; i ++)
        if(dp[i][i + n - 1] == maxn)
            cout << i << ' ' ;
}

到了这里,关于P4342 [IOI1998]Polygon —— 断链成环的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • P1012 [NOIP1998 提高组] 拼数

    设有 �n 个正整数 �1…��a1​…an​,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 第一行有一个整数,表示数字个数 �n。 第二行有 �n 个整数,表示给出的 �n 个整数 ��ai​。 一个正整数,表示最大的整数 输入 #1 复制 输出 #1 复制 输入 #

    2023年04月08日
    浏览(36)
  • P1013 [NOIP1998 提高组] 进制位

    著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如: 其含义为: �+�=�L+L=L,�+�=�L+K=K,�+�=�L+V=V,�+�=�L+E=E �+�=�K+L=K,�+�=�K+K=V,�+�=�K+V=E,�+�=��K+E=KL ⋯⋯ �+�=��E+E=KV 根据这些规则可推

    2023年04月08日
    浏览(38)
  • 新手入门深度学习 | 6-1:LeNet-5(1998年)详解

    🔗 运行环境:python3 🚩 作者:K同学啊 🥇 精选专栏: 《深度学习100例》 🔥 推荐专栏: 《新手入门深度学习》 📚 选自专栏: 《Matplotlib教程》 🧿 优秀专栏: 《Python入门100题》 传统的LeNet-5网络最初是为手写数字识别而设计的,由两个卷积层、两个池化层和三个全连接

    2024年02月11日
    浏览(34)
  • TCP网络三次握手(链接请求)和四次挥手(断链请求),FIN报文和RST报文

    本文直接将直接开始流程,部分东西不在做解释, 握手是建立连接,挥手是断开连接 标记位 SYN : 1 标记时表示希望创建连接 FIN: 1 标记时表示希望断开连接 ACK: 1 标记时确认号字段有效 RST: 1 标记时表示TCP连接出现异常,需要断开。 。。。。 序列号 : 在初次建⽴连接

    2024年04月15日
    浏览(47)
  • 【华为OD机考 统一考试机试C卷】 环中最长子串/字符成环找偶数O(C++ Java JavaScript Python C语言)

    目前在考C卷,经过两个月的收集整理, C卷真题已基本整理完毕 抽到原题的概率为2/3到3/3, 也就是最少抽到两道原题。 请注意:大家刷完C卷真题,最好要把B卷的真题刷一下,因为C卷的部分真题来自B卷。 另外订阅专栏还可以联系笔者开通在线OJ进行刷题,提高刷题效率。

    2024年01月25日
    浏览(43)
  • 如何判断两个多边形是否相交?——多边形相交判定算法详解

    如何判断两个多边形是否相交?——多边形相交判定算法详解 在计算机图形学中,判断两个多边形是否相交是一项很重要的任务。这涉及到各种应用场景,如碰撞检测、模拟物理效果等。在本篇文章中,我们将会介绍多边形相交判定算法的相关知识和实现方式。 首先,我们

    2024年02月14日
    浏览(67)
  • opencv 之 外接多边形(矩形、圆、三角形、椭圆、多边形)使用详解

    本文主要讲述opencv中的外接多边形的使用: 多边形近似 外接矩形、最小外接矩形 最小外接圆 外接三角形 椭圆拟合 凸包 将重点讲述最小外接矩形的使用 给一个opencv官方的例程: 过程图像如下: 椭圆拟合一般用于轮廓提取之后: 凸包绘制 计算两个旋转矩形交集: C++版的最

    2024年02月09日
    浏览(106)
  • 全球公链进展| 坎昆升级范围确定;Polygon 推出 Polygon 2.0;BEP-126 已成功部署到主网

    过去一周,明星项目动态如下: 最新以太坊开发者会议最终确定了坎昆升级的范围; BNB Chain 官方宣布 BEP-126 已经成功部署到主网; Polygon 宣布推出 Polygon 2.0; LayerZero 新增支持 Scroll 测试网; Sei Network 将重新开放跨链桥 Sei Bridge 测试活动 第 111 次以太坊核心开发者共识会议

    2024年02月10日
    浏览(41)
  • polygon mainnet 部署文档

    2023年05月12日
    浏览(39)
  • uniswapV3 polygon

    地址 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6 主要接口 quoteExactInputSingle quoteExactOutputSingle quoteExactOutput quoteExactInput … 地址 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 主要接口 exactInput exactInputSingle … 授权 approve 循环调用查询合约找到最优兑换路径 发起交易 授权时 tokenIn 和 tokenOut 都需要授权

    2023年04月19日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包