IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 洛谷P4342 [IOI1998]Polygon 题解 -> 正文阅读

[数据结构与算法]洛谷P4342 [IOI1998]Polygon 题解

洛谷P4342 [IOI1998]Polygon 题解

题目链接:P4342 [IOI1998]Polygon

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

img

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

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

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

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

img

这里每条边的运算符旁边的数字为边的编号,不拿来计算

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

3 ≤ n ≤ 50 3 \le n\le 50 3n50

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

容易发现我们需要断环为链,然后区间dp

注意到存在负数,而负负得正,说明不是简单的区间dp

不难发现两个负的极小值之乘积对答案有更大贡献

考虑维护区间最大值的同时维护区间最小值

即,设 f [ i ] [ j ] f[i][j] f[i][j] 为区间 [ i , j ] [i,j] [i,j] 的最大值, g [ i ] [ j ] g[i][j] g[i][j] 为区间 [ i , j ] [i,j] [i,j] 的最小值

当符号为"加"时,显然有
f [ i ] [ j ] = max ? i ≤ k < j ( f [ i ] [ j ] , f [ i ] [ k ] + f [ k + 1 ] [ j ] ) g [ i ] [ j ] = min ? i ≤ k < j ( g [ i ] [ j ] , g [ i ] [ k ] + g [ k + 1 ] [ j ] ) \begin{aligned} f[i][j]=&\max_{i\le k < j}(f[i][j],f[i][k]+f[k+1][j]) \\g[i][j]=&\min_{i\le k < j}(g[i][j],g[i][k]+g[k+1][j]) \end{aligned} f[i][j]=g[i][j]=?ik<jmax?(f[i][j],f[i][k]+f[k+1][j])ik<jmin?(g[i][j],g[i][k]+g[k+1][j])?

当符号为"乘"时

因为我们并不知道最大值是否非负,直接把所有情况都列出即可
f [ i ] [ j ] = max ? i ≤ k < j ( f [ i ] [ j ] , f [ i ] [ k ] × f [ k + 1 ] [ j ] , g [ i ] [ k ] × g [ k + 1 ] [ j ] , f [ i ] [ k ] × g [ k + 1 ] [ j ] , g [ i ] [ k ] × f [ k + 1 ] [ j ] ) g [ i ] [ j ] = min ? i ≤ k < j ( g [ i ] [ j ] , f [ i ] [ k ] × f [ k + 1 ] [ j ] , g [ i ] [ k ] × g [ k + 1 ] [ j ] , f [ i ] [ k ] × g [ k + 1 ] [ j ] , g [ i ] [ k ] × f [ k + 1 ] [ j ] ) \begin{aligned} f[i][j]=&\max_{i\le k < j}(f[i][j],f[i][k]\times f[k+1][j],g[i][k]\times g[k+1][j],f[i][k]\times g[k+1][j],g[i][k]\times f[k+1][j])\\ g[i][j]=&\min_{i\le k < j}(g[i][j],f[i][k]\times f[k+1][j],g[i][k]\times g[k+1][j],f[i][k]\times g[k+1][j],g[i][k]\times f[k+1][j]) \end{aligned} f[i][j]=g[i][j]=?ik<jmax?(f[i][j],f[i][k]×f[k+1][j],g[i][k]×g[k+1][j],f[i][k]×g[k+1][j],g[i][k]×f[k+1][j])ik<jmin?(g[i][j],f[i][k]×f[k+1][j],g[i][k]×g[k+1][j],f[i][k]×g[k+1][j],g[i][k]×f[k+1][j])?
时间复杂度 O ( n 3 ) O(n^3) O(n3)

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f
#define N (int)(120)
int n,a[N],f[N][N],g[N][N];
char op[N];
int max5(int a,int b,int c,int d,int e)
{return max(a,max(b,max(c,max(d,e))));}
int min5(int a,int b,int c,int d,int e)
{return min(a,min(b,min(c,min(d,e))));}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n;
    for(int i=1; i<=n; i++)
    {
        cin >> op[i] >> a[i];
        op[i+n]=op[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 i=1; i<=2*n; i++)
        f[i][i]=g[i][i]=a[i];
    for(int len=1; len<=n; ++len)
        for(int i=1; i+len-1<=2*n; i++)
        {
            int j=i+len-1;
            for(int k=i; k<j; k++)
            {
                if(op[k+1]=='x')
                {
                    f[i][j]=max5(f[i][j],f[i][k]*f[k+1][j],g[i][k]*g[k+1][j],f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]);
                    g[i][j]=min5(g[i][j],f[i][k]*f[k+1][j],g[i][k]*g[k+1][j],f[i][k]*g[k+1][j],g[i][k]*f[k+1][j]);
                }else
                {
                    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]);
                }
            }
        }
    int ans=-INF,ok=0;
    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)
        {
            if(!ok)ok=1,cout << i;
            else cout << " " << i;
        }
    cout << endl;
    return 0;
}

转载请说明出处

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:54:13  更:2022-05-18 17:56:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:04:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码