[IOI1998] Polygon (区间dp,和石子合并很相似)
题意:
给你一个多边形(可以看作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,和石子合并很相似)的更多相关文章
- IOI1998 Polygon [区间dp]
[IOI1998]Polygon 题意翻译 题目可能有些许修改,但大意一致 多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4.每个顶点用整数标记,每个边用符号+(加)或符号*(乘 ...
- nyoj737区间dp(石子合并)
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的 ...
- hihocoder1636 Pangu and Stones(区间DP(石子合并变形))
题目链接:http://hihocoder.com/problemset/problem/1636 题目大意:有n堆石头,每次只能合并l~r堆,每次合并的花费是要合并的石子的重量,问你合并n堆石子的最 ...
- 区间dp之 "石子合并"系列(未完结)
A. 石子合并<1> 内存限制:128 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统评测 方式:文本比较 题目描述 有N堆石子排成一排(n<=100),现要将石 ...
- 整数划分——区间dp(石子合并)
这不是将一个数以一来划分,而是把一个整数以位来划分 题目描述 如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式 ...
- 区间DP经典 石子合并
题目链接 题意:环形的一群石子,每次可以选择相邻的两堆合并,分数为新得到的一堆石子,求将这片石子合并成一堆的最大和最小分数 输入:第一行一个正整数n,其后n个数代表每堆石子的个数 分析:第一次写的时候 ...
- 【IOI1998】Polygon 区间DP
题意翻译 题目可能有些许修改,但大意一致 多边形是一个玩家在一个有n个顶点的多边形上的游戏,如图所示,其中n=4.每个顶点用整数标记,每个边用符号+(加)或符号*(乘积)标记. 第一步,删除其中一条边 ...
- POJ 1179 - Polygon - [区间DP]
题目链接:http://poj.org/problem?id=1179 Time Limit: 1000MS Memory Limit: 10000K Description Polygon is a ...
- 2017北京网络赛 J Pangu and Stones 区间DP(石子归并)
#1636 : Pangu and Stones 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 In Chinese mythology, Pangu is the fi ...
随机推荐
- 对微信小程序的生命周期进行扩展 – Typescript 篇
最近利用业余时间倒腾了一个微信小程序,主要目的是横向比较一些业界小程序平台的架构和做法.因为有在其他平台长期的开发经验,对于小程序的一些机制做了一些辩证的思考.例如,小程序的页面,其实不是一个页面,而 ...
- python作业完成简单的文件操作
题目 请创建以学号命名的目录,在该目录中创建名称为file1.txt的文件,并将自己的个人信息(序号.姓名以及班级)等写入该文件:然后并读取文件中的内容到屏幕上:接着重新命名该文件为file2.txt ...
- for update语句锁机制问题
数据库小知识学习系列 问题: MySQL InnoDB中,select where xxx=123 for update:该xxx没有索引,是使用表锁还是全部数据加行锁? 答: InnoDB引擎(默认 ...
- 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC
文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...
- leetcode 31. Next Permutation (下一个排列,模拟,二分查找)
题目链接 31. Next Permutation 题意 给定一段排列,输出其升序相邻的下一段排列.比如[1,3,2]的下一段排列为[2,1,3]. 注意排列呈环形,即[3,2,1]的下一段排列为[1 ...
- URL重定向 - Pikachu
概述: 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方.如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话就可能 ...
- 实现简易版德州扑克|学习麻瓜编程以项目为导向入门前端 HTML+CSS+JS
实现简易版德州扑克 1.先上达到网页效果图(简易版德州扑克) 网页分为发牌区和牌池,上面为发牌区,下面是牌池区 2. 代码实现 2.1 HTML和JS代码 ` <link rel="s ...
- PeleeNet:精修版DenseNet,速度猛增至240FPS | NeurIPS 2018
PeleeNet是DenseNet的一个变体,没有使用流行的深度可分离卷积,PeleeNet和Pelee仅通过结构上的优化取得了很不错的性能和速度,读完论文可以学到很多网络设计的小窍门. 来源:晓 ...
- 处理 K8S Orphaned pod found - but volume paths are still present on disk 孤儿pod
问题概述 查看kubelet或/var/log/messages日志一直包错,发现是孤儿pod,是由于其pod被删除后存储路径还保存在磁盘. 报错如下 [root@node5 ~]# journalc ...
- Vue 3自定义指令开发
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 什么是指令(directive) 在Angular和Vue中都有Direct ...