题意:

给你一个多边形(可以看作n个顶点,n-1条边的图),每一条边上有一个符号(+号或者*号),这个多边形有n个顶点,每一个顶点有一个值

最初你可以把一条边删除掉,这个时候这就是一个n个顶点,n-2条边的图

如果顶点i和j之间有边,那么你可以把i点和j点合并成一个点,把这个点替换掉i、j两个点,这个新点的值是i+j 或者 i*j (这个是要看连接i和j两点的边上的符号)

经过若干次操作之后剩下一个点,这个点的值最大是多少

题解:

这道题目和石子合并题目很相似,这里先说一下石子合并

题目:

有N堆石子围成一个圆,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花费为新合成的一堆石子的数量。求将这N堆石子合并成一堆的总花费最小(或最大)。

我们来分析一下,给你 4 堆石子:4,5,6,7,按照下图所示合并

这种合并方式的花费为:4+5+9+6+15+7=46

这种合并也就是4->5->6->7按照这个方向进行

那我们先合并前3堆石子:4+5+9+6

这个花费就是:第一堆和第二堆合并的花费+第一堆和第二堆合并之后的数量+第三堆的数量

那我们先合并前4堆石子:4+5+9+6+15+7

这个花费就是:第一堆和第二堆和第三堆合并的花费(也就是4+5+9+6)+第一堆和第二堆和第三堆合并之后的数量+第四堆的数量

大问题分解成了小问题,而且大问题包含了小问题的解,大问题和小问题同质同解。完完全全满足dp的性质。

剩下的就是从中找到最优解,因为当前是从1->2->3->4的顺序去合并的,还有(1->2)->(3->4)或者1->(2->3->4)的顺序,原理一样,这里面因为第二第三部分是固定的,所以只需要得到小问题的最优解,就可以求得大问题的最优解了。这一点我们可以把原序列复制一份追加到原序列尾部,然后使用区间dp枚举就可以了

这里给出石子合并问题求最大花费的代码:dp[i][j]表示:从石子i合并到石子j所能得到的最大花费

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=450;//区间长度为2*n
4 int dp[maxn][maxn];
5 int sum[maxn];//前缀和数组
6 int a[maxn];//每堆石子的个数
7 int main()
8 {
9 int n,x;
10 sum[0]=0;
11 while(scanf("%d",&n)!=EOF){
12 memset(dp,0,sizeof(dp));
13 memset(sum,0,sizeof(sum));
14 for(int i=1;i<=n;i++){
15 scanf("%d",&a[i]);
16 sum[i]=sum[i-1]+a[i];//预处理
17 dp[i][i]=0;
18 }
19
20 int in=1;//首尾相连之后
21 for(int i=n+1;i<=2*n;i++)
22 sum[i]+=(sum[i-1]+a[in++]);
23
24 for(int len=2;len<=n;len++)//枚举区间长度
25 {
26 for(int i=1;i<=2*n;i++)//枚举区间起点
27 {
28 int j=i+len-1;//区间终点
29 if(j>n*2) break;//越界结束
30 for(int k=i;k<j;k++)//枚举分割点,构造状态转移方程
31 {
32 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+(sum[j]-sum[i-1]));
33 }
34 }
35 }
36 int MAX=-1;
37 for(int i=1;i<=n;i++)//枚举环状序列的起点,长度为n
38 MAX=max(dp[i][i+n-1],MAX);//求最大值
39 printf("%d\n",MAX);
40 }
41 return 0;
42 }

回归原题,这个题目如果所有边的符号都是+号,那就和石子合并一样了

这里多了一个*号,那么两个很小的负数相乘也可以得到一个很大的值,这样的话,我们可以开一个三维dp,dp[i][j][k]:如果k==1,那就保存的是dp[i][j]的max

如果k==0,那就保存dp[i][j]的最小值

其他和正常区间dp一样

代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
typedef long long ll;
const int maxn=55;
const int INF=0x3f3f3f3f;
const double blo=(1.0+sqrt(5.0))/2.0;
const double eps=1e-8;
struct shudui
{
int a,b;
}que[maxn];
int dp[maxn][maxn][2],num[maxn],str[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
char s[maxn];
for(int i=1;i<=2*n;++i)
{
if(i%2)
{
scanf("%s",s);
str[i/2]=s[0];
}
else
{
scanf("%d",&num[(i-1)/2]);
}
}
str[n]=str[0];
for(int i=0;i<n;++i)
{
for(int j=0;j<n;++j)
{
if(i==j)
dp[i][j][0]=dp[i][j][1]=num[i];
else
{
dp[i][j][0]=INF;
dp[i][j][1]=-INF;
}
}
}
for(int len=1;len<n;++len)
{
for(int i=0;i<n;++i)
{
//int j=(i+len)%n;
int j=(i+len);
for(int k=i;k<j;++k)
{
if(str[(k+1)%n]=='t')
{
dp[i][j%n][1]=max(dp[i][j%n][1],dp[i][k%n][1]+dp[(k+1)%n][j%n][1]);
dp[i][j%n][0]=min(dp[i][j%n][0],dp[i][k%n][0]+dp[(k+1)%n][j%n][0]);
}
else
{
dp[i][j%n][1]=max(dp[i][j%n][1],dp[i][k%n][1]*dp[(k+1)%n][j%n][1]);
dp[i][j%n][1]=max(dp[i][j%n][1],dp[i][k%n][0]*dp[(k+1)%n][j%n][0]);
dp[i][j%n][0]=min(dp[i][j%n][0],dp[i][k%n][0]*dp[(k+1)%n][j%n][1]);
dp[i][j%n][0]=min(dp[i][j%n][0],dp[i][k%n][1]*dp[(k+1)%n][j%n][0]);
dp[i][j%n][0]=min(dp[i][j%n][0],dp[i][k%n][0]*dp[(k+1)%n][j%n][0]);
}
}
}
}
//printf("%d %d %d %d\n",dp[1][2][1],dp[2][1][1],dp[2][3][1],dp[3][2][1]);
int maxx=-INF,index=0;
for(int i=0;i<n;++i)
{
maxx=max(maxx,dp[i][(i+n-1)%n][1]);
}
for(int i=0;i<n;++i)
{
if(dp[i][(i+n-1)%n][1]==maxx)
{
//printf("%d %d\n",i,(i+n-1)%n);
que[index++].a=i+1;
//que[index++].b=max((i+n-1)%n,i)+1;
//que[index++].a=i+1;
}
}
printf("%d\n",maxx);
for(int i=0;i<index;++i)
{
//printf("%d %d\n",que[i].a,que[i].b);
if(i==index-1)
printf("%d\n",que[i].a);
else printf("%d ",que[i].a);
}
}
return 0;
}

[IOI1998] Polygon (区间dp,和石子合并很相似)的更多相关文章

  1. IOI1998 Polygon [区间dp]

    [IOI1998]Polygon 题意翻译 题目可能有些许修改,但大意一致 多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4.每个顶点用整数标记,每个边用符号+(加)或符号*(乘 ...

  2. nyoj737区间dp(石子合并)

    石子合并(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述     有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的 ...

  3. hihocoder1636 Pangu and Stones(区间DP(石子合并变形))

    题目链接:http://hihocoder.com/problemset/problem/1636 题目大意:有n堆石头,每次只能合并l~r堆,每次合并的花费是要合并的石子的重量,问你合并n堆石子的最 ...

  4. 区间dp之 "石子合并"系列(未完结)

    A. 石子合并<1> 内存限制:128 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统评测 方式:文本比较   题目描述 有N堆石子排成一排(n<=100),现要将石 ...

  5. 整数划分——区间dp(石子合并)

    这不是将一个数以一来划分,而是把一个整数以位来划分 题目描述 如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式 ...

  6. 区间DP经典 石子合并

    题目链接 题意:环形的一群石子,每次可以选择相邻的两堆合并,分数为新得到的一堆石子,求将这片石子合并成一堆的最大和最小分数 输入:第一行一个正整数n,其后n个数代表每堆石子的个数 分析:第一次写的时候 ...

  7. 【IOI1998】Polygon 区间DP

    题意翻译 题目可能有些许修改,但大意一致 多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4.每个顶点用整数标记,每个边用符号+(加)或符号*(乘积)标记. 第一步,删除其中一条边 ...

  8. POJ 1179 - Polygon - [区间DP]

    题目链接:http://poj.org/problem?id=1179 Time Limit: 1000MS Memory Limit: 10000K Description Polygon is a ...

  9. 2017北京网络赛 J Pangu and Stones 区间DP(石子归并)

    #1636 : Pangu and Stones 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 In Chinese mythology, Pangu is the fi ...

随机推荐

  1. 【渲染引擎】Blender的2021年最佳渲染引擎(上)

    Blender最终摆脱了"古怪的孩子"的装束,并穿上了更为严肃和受人尊敬的" 3D强者". 它已在业界获得广泛认可,许多工作室和艺术家正在将其纳入他们的产品线. ...

  2. oracle创建恢复编录(recovery catalog)

    1.在要作为恢复编录的数据库创建用户 create user rman identified by oracle default tablespace system temporary TABLESP ...

  3. me21n增强BADI:ME_PROCESS_PO_CUST之process_account

    当实施ME_PROCESS_PO_CUST这个badi来增强ME21N的时候,用了到方法process_account,既对ME21N的行项目的科目分配做增强.主要用到如下类: IF_PURCHASE ...

  4. 1.5V转3V电源芯片,1.5V转3V稳压芯片

    1.5V干电池的供电电压一般是0.9V-1.6V左右,因为供电电压不稳,所以需要1.5V转3V的稳压电源芯片,当0.9V-1.6V输入电压时,输出电压能稳定3V输出,给模块供电,MCU供电,LED灯供 ...

  5. 【2020CSP-S模拟赛day5】总结

    爆零自闭赛 写在前面 于2022.11.1 这一次题目质量很高(以至于什么都不会) 再一度体验了省选Orz.比赛大体情况,刨去std, wzc神仙230分,比剩下的加起来都高.zyz神仙60分. 其余 ...

  6. 百度文库Word下载器

    最近我妈的文库VIP用完了,但还有很多资源要下载,于是我便在网上找下载工具. 总算找到个完美的!(虽然没界面) 既然没界面,那就自己写一个呗! 原作者 该程序的下载和写入部分由地球守卫者制作 原文链接 ...

  7. IDEA SSM+MAVEN+JWT 图书管理系统

    压缩包内含有MAVEN,TOMCAT,需要手动对IDEA进行配置.同时也包含数据库文件. 项目搭载了swagger,可以方便地对接口进行测试 在开发的过程中我也进行了一些记录,可以参考https:// ...

  8. (003)每日SQL学习:普通视图和物化视图

    关于这一点一直就是很懵懂的状态,今天特意网上查了一下资料,以下摘抄网上比较好的答案.以作记录. 普通视图和物化视图的区别答曰:普通视图和物化视图根本就不是一个东西,说区别都是硬拼到一起的,首先明白基本 ...

  9. FFmpeg libswscale源码分析1-API介绍

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/14349382.html libswscale 是 FFmpeg 中完成图像尺寸缩放和像素 ...

  10. Java——时间和日期处理

    Date Date date = new Date(); 获取时间 Date d = new Date(); // Date d2=new Date(System.currentTimeMillis( ...