首页 > 其他分享 >luogu P4342[IOI1998]Polygon

luogu P4342[IOI1998]Polygon

时间:2024-05-11 20:41:06浏览次数:18  
标签:begin end Polygon min luogu P4342 max aligned dp

阅读前需

深剖析分系列是记录我个人的做题思路,实现过程的全面分析,存在内容可靠、思路健全、分析到位、试错纠错等优于一般题解的特征,其中,Quest部分表示探索问题,我会在此提出做题时的想法、问题,并在内容中得到解决,因此建议从上到下按序浏览,以防出现思路断层,内容不衔接的情况,感谢理解与支持!

题目大意

给定一个多边形,对应节点上标记有一个数字,每条边上标记有加(t)或乘(x)表示相邻两个节点可进行的操作,操作后两个节点将合并为一个节点,首先删去一条边(不进行操作),之后在若干次操作后使得该多边形只剩一个节点,且要求所剩节点标记的数最大化,询问最大的数字

题目分析image

如图是题目所给出的示例图,我们可以通过模拟该图来得到我们代码实现的过程。

Quest1:如何处理环?

我们先假定删除了某条边,注意这里第一步是删除,并没有进行操作。
然后我们就要一系列的合并操作,完成之后又要换另一条边删掉,继续下去。。。
很明显这是一个很暴力的算法,而对于这种环状的区间dp问题,大家应该能反应出来,我们可以通过破环成链的方法,具体的就是将原本的一个环在复制一遍,形成一个长度为原先二倍的大环,这个时候随便断哪一条边都没有问题了,所以我们下面的操作中默认断掉了第一条边,或者说是第一条输入的边。

Ques2:如何初步验证?

Part1:试验最初思路

之后我们可以开始合并操作,在这道题中,我们应当能发现现在是对一条链进行的区间合并操作,很容易就想到区间dp,因此,我们会用到下述转移方程:

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

不过与常规区间dp的不同之处也显而易见,我们的转移过程中不一定只涉及到加法这一操作,而对于乘法的处理,或许会想到:

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

似乎到这一步就已经大功告成了,于是我们自信满满的打出以下代码:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,ans=-0x3f3f3f3f;
char op[100];
int dp[200][200];
int main(){
	cin >> n;
	memset(dp,-0x3f,sizeof dp);
	for(int i=1;i<=n;i++){
		cin >> op[i-1] >> dp[i][i];
		op[i+n-1]=op[i-1];
		dp[i+n][i+n]=dp[i][i];
	}
	for(int len=2;len<=n;len++)
		for(int l=1;l<=n;l++){
			int r=l+len-1;
			for(int k=l;k<r;k++){
				if(op[k]=='t') dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);
				if(op[k]=='x') dp[l][r]=max(dp[l][r],dp[l][k]*dp[k+1][r]);
			}
		}
	for(int l=1;l<=n;l++) ans=max(ans,dp[l][l+n-1]);
	cout << ans << '\n';
	for(int l=1;l<=n;l++) if(ans==dp[l][l+n-1]) cout << l << ' ';
	return 0;
}

然后我们成功的wa掉了这道题,还只有二十分。。。

Part2:找到问题所在

我们很容易可以发现,这道题的数据范围从负数开始,因此所有的数据中就存在负负得正的情况,这应该不难想到,因此我们就会有下面的情况:

  • 正*正=更大的正数
  • 负*负=更大的正数
  • 正(负)*负(正)=更小的负数
    我们可以很简单的根据数据判断出数据的绝对值只会越乘越大,而对于存在正负两类情况,这就显得很麻烦了,不过只要耐心分析,应该还是没问题的!

Quest3:如何最终实现?

Part1:得到正确思路

我们不能只单单靠一个f数组来实现我们的全部过程,对于负数我们必须拿出额外的部分来处理,我们用g数组记录过程当中的最小值,我们首先可以写出加法的处理过程:

\[\begin{aligned}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]) \end{aligned} \]

那么对于乘法我们就不得不分类讨论了:

  1. \(f[i][k]>0,f[k+1][j]>0,g[i][k]>0,g[k+1][j]>0\)
    这种情况就很简单,都是正数,那其实\(g\)的操作等同于没有,因为原则上越乘绝对值越大嘛,对于此,我们应该的处理是:

\[\begin{aligned}f[i][j] = max(f[i][j],f[i][k]*f[k+1][j]) \\ \\ g[i][j] = min(g[i][j],j[i][k]*g[k+1][j]) \end{aligned} \]

  1. $ f[i][k]>0.f[k+1][j]>0,g[i][k]>0,g[k+1][j]<0 $
    这个时候最小值出现了一个负数,秉承着越乘绝对值越大的原则,能写出下面这个式子:

\[\begin{aligned} f[i][j] = max(f[i][j],f[i][k]*f[k+1][j]) \\ \\ g[i][j] = min(g[i][j],f[i][k]*g[k+1][j]) \end{aligned} \]

  1. $ f[i][k]>0,f[k+1][j]>0,g[i][k]<0,g[k+1][j]<0 $
    这种情况和2如出一辙,因此操作上也是一样的:

\[\begin{aligned} 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]) \end{aligned} \]

  1. $ f[i][k]>0,f[k+1][j]>0,g[i][k]<0,g[k+1][j]<0 $
    现在就大为不同了,我们要考虑的,现在乘法所得一定比原先更大且为正数:

\[\begin{aligned} 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]*f[k+1][j],g[i][k]*g[k+1][j]) \end{aligned} \]

为什么要处理\(g\)呢,其实答案显然,我们的\(g\)在这时候可能没有定义出值,也有可能当前所得比原先的值小,越乘绝对值越大指的是所得的积的绝对值比原先两个数的绝对值大。

挖趣,到这里就已经四种情况了,看来又要写好多好长的式子了。。。老实讲,这么算我们得写16个,懒。。所以我们把一正一负的自动归为一类!就像是上面的2,3一样。那这样子我们就写9个,算上那一个多的最多10个,OK!

从头写一遍吧TAT。。

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

\[\begin{aligned} f[i][j]=max(f[i][k]×f[k+1][j]) \\ \\ g[i][j]=min(g[i][k]×g[k+1][j]) \end{aligned} \]

  1. $ f[i][k],g[i][k],f[k+1][j]>0,g[k+1][j]<0: $

\[\begin{aligned} f[i][j]=max(f[i][k]×f[k+1][j]) \\ \\ g[i][j]=min(f[i][k]×g[k+1][j]) \end{aligned} \]

  1. $ f[i][k],g[i][k]>0,f[k+1][j],g[k+1][j]<0: $

\[\begin{aligned} f[i][j]=max(g[i][k]×f[k+1][j]) \\ \\ g[i][j]=min(f[i][k]×g[k+1][j]) \end{aligned} \]

  1. $ f[i][k],f[k+1][j],g[k+1][j]>0,g[i][k]<0: $

\[\begin{aligned} f[i][j]=max(f[i][k]×f[k+1][j]) \\ \\ g[i][j]=min(g[i][k]×f[k+1][j]) \end{aligned} \]

  1. $ f[i][k],f[k+1][j]>0,g[i][k],g[k+1][j]<0: $

\[\begin{aligned} 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]) \end{aligned} \]

  1. $ f[i][k]>0,g[i][k],f[k+1][j],g[k+1][j]<0: $

\[\begin{aligned} f[i][j]=max(g[i][k]×g[k+1][j]) \\ \\ g[i][j]=min(f[i][k]×g[k+1][j]) \end{aligned} \]

  1. $ f[k+1][j],g[k+1][j]>0,f[i][k],g[i][k]<0: $

\[\begin{aligned} f[i][j]=max(f[i][k]×g[k+1][j]) \\ \\ g[i][j]=min(g[i][k]×f[k+1][j]) \end{aligned} \]

  1. $ f[k+1][j]>0,f[i][k],g[i][k],g[k+1][j]<0: $

\[\begin{aligned} f[i][j]=max(g[i][k]×g[k+1][j]) \\ \\ g[i][j]=min(g[i][k]×f[k+1][j]) \end{aligned} \]

  1. $ f[i][k],g[i][k],f[k+1][j],g[k+1][j]<0: $

\[\begin{aligned} f[i][j]=max(g[i][k]×g[k+1][j]) \\ \\ g[i][j]=min(f[i][k]×f[k+1][j]) \end{aligned} \]

哇呜呜,简直就是史诗级大作

标签:begin,end,Polygon,min,luogu,P4342,max,aligned,dp
From: https://www.cnblogs.com/sleepyday/p/18185214

相关文章

  • luogu P6329 【模板】点分树 | 震波
    //【模板】点分树|震波//https://www.luogu.com.cn/problem/P6329#include<bits/stdc++.h>#definedebug(a)cerr<<"Line:"<<__LINE__<<""#a<<endl#defineprint(a)cerr<<#a"="<<(a)<<endl#d......
  • [992] Remove holes within polygons in a shapefile
    Toremoveholeswithinpolygonsinashapefile,youcanusethegeopandaslibraryinPython.Here'showyoucandoit:importgeopandasasgpd#Readtheshapefilegdf=gpd.read_file('path_to_shapefile.shp')#Removeholeswithinpolygon......
  • [分块] [Luogu AT_joisc2014_c] 历史研究
    题目描述IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记。JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件。日记中记录了连续\(N\)天发生的事件,大约每天发生一件。事件有种类之分。第\(i\)天发生的......
  • 树上点差分的经典应用 LuoguP3258松鼠的新家
    树上点差分的核心就是如何避免重复,即正确的运用差分数组例如a,b点路径上点权值加1,则把a,b路径找到,并找到其LCA,此时可以把a到根,b到根这两条路径看出两条链,把每条链看出我们熟悉的顺序差分结构.以其中一条链为例子,把a当成数组的起点,根当成数组的末尾,进行差分,显然有C[a]+......
  • ConvexPolygonGame
    博弈#计算几何这要先手可以操作,那么一定存在必胜策略所以题目转化为判原来的多边形内有没有三个不共线的点把所有点求出来判共线即可//Author:xiaruizeconstintINF=0x3f3f3f3f3f3f3f3f;constintMOD=1000000007;constintN=2e5+10;intn;piia[N];int......
  • [POI2007] [LUOGU P3451]旅游景点 Tourist Attractions
    本题解由于作者太菜在POI及LUOGU上会TLE,该题解主要讲思路,剩下的内存优化请各位大佬自行补充,欢迎评论区讨论本题解运行时间10406ms,空间194584KiB题目描述FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情。经过这些城......
  • luoguP1024-二分
    题目链接实数二分:实数二分不存在边界问题,二分时可以设立循环次数或确立精度1.若存在2个数x1和x2,且x1<x2,f(x1)×f(x2)<0之间一定存在它的一个浮点数根2.且题目给定实根范围在-100~100之间,按位枚举方程=0时,显然x是方程的一个整数实根题目描述有形如:ax3+bx2+cx+d=0这样......
  • luoguP1102-双指针
    题目链接:P1102A-B数对-洛谷|计算机科学教育新生态(luogu.com.cn)利用单调性求解双指针解法:排序构造出区间单调,则若存在目标值B,B在序列中一定为连续区间,此时通过双指针l和r,此时维护一段区间:有S[L]大于S[I]-C,S[R]大于等于S[I]-C,此时我们枚举每一位,若存在A......
  • [ABC211F] Rectilinear Polygons 题解
    [ABC211F]RectilinearPolygons题解思路什么的上一篇题解已经写的非常明白了,这里只是提供一个补充&另一个实现的方法。思路解析先说结论:扫描线。顾名思义,扫描线的本质就是用一条线沿着\(x\)或\(y\)轴扫过去,每碰到一条边就记录一下加边后是面积是增加还是减少,然后用树状......
  • Luogu P8710 [蓝桥杯 2020 省 AB1] 网络分析 题解 [ 绿 ] [ 带权并查集 ]
    原题分析本题由于从一个节点发信息,同一个集合内的所有点都会收到信息,显然是一道要求维护各节点间关系的题,因此采用并查集的数据结构进行求解。但由于维护关系的同时还要维护权值,所以采用带权并查集,它是一种能维护某个节点与其祖宗节点之间关系的数据结构。带权并查集找父亲的......