DP中环形处理

对于DP中存在环的情况,大致有两种处理的方法:

  • 对于很多的区间DP来说,很常见的方法就是把原来的环从任意两点断开(注意并不是直接删掉这条边),在复制一条一模一样的链在这条链的后方,当做线性问题来解,即可实现时间复杂度降维。
  • 情况一:将原来的环从任意两点断开,再当做线性问题来解。情况二:添加一些特殊条件,将断开的前后强行连接起来。两种情况取其中的最优解即可。亦可以实现时间复杂度的降维。

本篇博客将对于第一种情况进行分析。

根据一道例题来探讨。

POJ 1179 Polygon

题目链接:

(题目翻译将在文末给出)

Description

Polygon is a game for one player that starts on a polygon with N vertices, like the one in Figure 1, where N=4. Each vertex is labelled with an integer and each edge is labelled with either the symbol + (addition) or the symbol * (product). The edges are numbered from 1 to N.

On the first move, one of the edges is removed. Subsequent moves involve the following steps:

�pick an edge E and the two vertices V1 and V2 that are linked by E; and

�replace them by a new vertex, labelled with the result of performing the operation indicated in E on the labels of V1 and V2.

The game ends when there are no more edges, and its score is the label of the single vertex remaining.

Consider the polygon of Figure 1. The player started by removing edge 3. After that, the player picked edge 1, then edge 4, and, finally, edge 2. The score is 0.

Write a program that, given a polygon, computes the highest possible score and lists all the edges that, if removed on the first move, can lead to a game with that score.

Input

Your program is to read from standard input. The input describes a polygon with N vertices. It contains two lines. On the first line is the number N. The second line contains the labels of edges 1, ..., N, interleaved with the vertices' labels (first that of the vertex between edges 1 and 2, then that of the vertex between edges 2 and 3, and so on, until that of the vertex between edges N and 1), all separated by one space. An edge label is either the letter t (representing +) or the letter x (representing *).

3 <= N <= 50

For any sequence of moves, vertex labels are in the range [-32768,32767].

Output

Your program is to write to standard output. On the first line your program must write the highest score one can get for the input polygon. On the second line it must write the list of all edges that, if removed on the first move, can lead to a game with that score. Edges must be written in increasing order, separated by one space.

Sample Input

4
t -7 t 4 x 2 x 5

Sample Output

33
1 2

Source

IOI 1998

分析

题目大意

给出一个多边形,删除一条边,合并剩下的点(若边的符号为x,则进行乘法;若边的符号为t,则进行加法)。问操作后剩下的点的值最大为多少。

样例简单解释

删除第1或第2条边,按照上述题意依此合并4,3,2或4,3,1,所以是\(5×2×4+(-7)\)

首先来考虑是一条链的情况

对于一个区间 \([l,r]\) 中,可以找到一个点 \(k\) \((k∈[l, r))\) ,通过合并区间 \([l,k]\) 与区间 \([k+1,r]\) 来更新区间\([l,r]\)的状态。

具体是什么状态?定义一个区间最大值与一个区间最小值。即定义 \(dp[i][j][0|1]\)来表示区间 \([l,j]\) 的最值。其中,0为最大值,1为最小值。

为何需要最小值?因为该数据中存在负数,负负得正,很有可能两个区间的最小值都为负数,他们的乘积远远大于这两个区间的最大值的乘积。

需要讨论两种情况

  • \(1\) 当两点之间为加号时。对于每一个k,都只能用两区间的最大值之和来更新合并区间的最大值,最小值同理。不可能用最大值与最小值之和来更新区间最值。
  • \(2\) 当两点之间为加号时。对于每一个k,用四种不同的搭配,考虑到不同正负的情况,来更新区间的最值:

    \(dp[l][k][1] * dp[k + 1][r][1]\)

    \(dp[l][k][0] * dp[k + 1][r][0]\)

    \(dp[l][k][1] * dp[k + 1][r][0]\)

    \(dp[l][k][0] * dp[k + 1][r][1]\)

若枚举删除每一条边,每次都来跑一遍DP,则时间复杂度为 \(O(n^4)\)。但本题数据不强,若规定 \(n≤100\),则必定会超时。

按照在复制一条一模一样的链在这条链的后方,当做线性问题来解这样来处理,则会将时间复杂度降到\(O(n^3)\)。

拿样例来举例:

原图:



化成一条链后:

在这条链上,\(dp[1][4]\) 就可以理解为删除边3后的最大值

同理,\(dp[2][5]\) 就可以理解为删除边2后的最大值

\(dp[3][6]\) 就可以理解为删除边1后的最大值

\(dp[4][7]\) 就可以理解为删除边4后的最大值

所以最大值就可以表示为 \(Max(dp(i,i+n-1))\)

这样就省略了很多重复的计算。

C++实现

#include <cstdio>
#define INF 0x3f3f3f3f
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
void Quick_Read(int &N) {
N = 0;
char c = getchar();
int op = 1;
while(c < '0' || c > '9') {
if(c == '-')
op = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
N = (N << 1) + (N << 3) + c - 48;
c = getchar();
}
N *= op;
}
const int MAXN = 105;
int dp[MAXN][MAXN][2];
int A[MAXN];
bool F[MAXN];
int n;
int ans = -INF;
void DP() {
for(int i = 1; i <= n; i++) {
A[i + n] = A[i];
F[i + n] = F[i];
}
n <<= 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
dp[i][j][0] = -INF;
dp[i][j][1] = INF;
}
for(int i = 1; i <= n; i++)
dp[i][i][1] = dp[i][i][0] = A[i];
for(int len = 2; len <= n; len++) {
for(int l = 1; l <= n - len + 1; l++) {
int r = l + len - 1;
for(int k = l; k < r; k++) {
if(F[k + 1]) {
for(int p = 0; p <= 1; p++)
for(int q = 0; q <= 1; q++) {
dp[l][r][0] = Max(dp[l][r][0], dp[l][k][p] * dp[k + 1][r][q]);
dp[l][r][1] = Min(dp[l][r][1], dp[l][k][p] * dp[k + 1][r][q]);
}
}
else {
dp[l][r][0] = Max(dp[l][r][0], dp[l][k][0] + dp[k + 1][r][0]);
dp[l][r][1] = Min(dp[l][r][1], dp[l][k][1] + dp[k + 1][r][1]);
}
}
}
}
for(int i = 1; i <= n; i++)
ans = Max(ans, dp[i][i + (n >> 1) - 1][0]);
printf("%d\n", ans);
for(int i = 1; i <= (n >> 1); i++)
if(dp[i][i + (n >> 1) - 1][0] == ans)
printf("%d ", i);
}
void Read() {
Quick_Read(n);
char c = getchar();
for(int i = 1; i <= n; i++) {
while(c != 't' && c != 'x')
c = getchar();
if(c == 'x')
F[i] = true;
Quick_Read(A[i]);
c = -1;
}
}
int main() {
Read();
DP();
return 0;
}

题目翻译

多边形是一个针对一个玩家的游戏,它从具有N个顶点的多边形开始,如图1所示,其中N = 4。每个顶点都标有整数,每个边都标有符号+(加法)或符号*(乘积)。边编号从1到N。

第一步,移除其中一个边缘。随后的移动涉及以下步骤:

拾取边E和由E链接的两个顶点V1和V2;

并用一个新的顶点替换它们,并在V1和V2的标签上标出执行E中指示的操作的结果。

当没有更多边时,游戏结束,其分数是剩余单个顶点的标签。

考虑图1的多边形。玩家首先移除边缘3。此后,玩家选择边缘1,然后选择边缘4,最后选择边缘2。得分为0。

编写一个程序,给定一个多边形,该程序将计算可能的最高得分并列出所有边缘,这些边缘如果在第一步移动时被移除,可能会导致具有该得分的游戏。

您的程序将从标准输入中读取。输入描述了一个具有N个顶点的多边形。它包含两行。第一行是数字N。第二行包含边1,...,N的标签,这些标签与顶点的标签交错(首先是边1和2之间的顶点的标签,然后是边之间的顶点的标签) 2和3,依此类推,直到边缘N和1)之间的顶点,都被一个空格隔开。边缘标签是字母t(代表+)或字母x(代表*)。

3 <= N <= 50

对于任何移动顺序,顶点标签都在[-32768,32767]范围内。

您的程序将写入标准输出。在第一行,您的程序必须编写输入多边形可获得的最高分数。在第二行中,它必须写出所有边缘的列表,如果在第一步中删除了这些边缘,则可以导致该分数的游戏。边必须以递增顺序书写,并以一个空格分隔。

DP中环形处理 +(POJ 1179 题解)的更多相关文章

  1. Mark一下, dp状态转移方程写对,可是写代码都错,poj 1651 poj 1179

    dp题: 1.写状态转移方程; 2.考虑初始化边界,有意义的赋定值.还没计算的赋边界值: 3.怎么写代码自底向上计算最优值 今天做了几个基础dp,所有是dp方程写对可是初始化以及计算写错 先是poj ...

  2. 区间DP中的环形DP

    vijos1312 链接:www.vijos.org/p/1312 题目分析:经典的环形DP(区间DP) 环形DP,首先解环过程,把数组复制一遍,n个数变成2n个数,从而实现解环 dp[i][j]表示 ...

  3. dp乱写2:论dp在不在dp中(但在dp范畴)内的应用

    最近正儿八经的学习了dp,有一些题目非常明显看出来就是dp了比如说:过河卒.方格取数.导弹拦截.加分二叉树.炮兵阵地更加明显的还有:采药.装箱问题.过河.金明的预算方案.今天来谈谈dp的dp在不在dp ...

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

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

  5. IOI 98 (POJ 1179)Polygon(区间DP)

    很容易想到枚举第一步切掉的边,然后再计算能够产生的最大值. 联想到区间DP,令dp[i][l][r]为第一步切掉第i条边后从第i个顶点起区间[l,r]能够生成的最大值是多少. 但是状态不好转移,因为操 ...

  6. POJ 1625 Censored!(AC自动机 + DP + 大数 + 拓展ASCII处理)题解

    题意:给出n个字符,p个病毒串,要你求出长度为m的不包含病毒串的主串的个数 思路:不给取模最恶劣情况$50^{50}$,所以用高精度板子.因为m比较小,可以直接用DP写. 因为给你的串的字符包含拓展A ...

  7. POJ 2752 Seek the Name, Seek the Fame(KMP中next的理解)题解

    题意: 要求你给出每个前后缀相同的串的长度,比如: "alala"的前缀分别为{"a", "al", "ala", &q ...

  8. poj 1179 Polygon

    http://poj.org/problem?id=1179 Polygon Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:  ...

  9. 概率dp的边界处理 POJ 2096

    题目地址:https://vjudge.net/problem/POJ-2096 说的是有n个bug,和s个系统.现在一个人一天能发现一个bug,它可能是任何一个系统中的,也可能会发现已经发现过的bu ...

随机推荐

  1. lvs搭建dr负载均衡集群

    一,查看本地centos的版本: [root@localhost lib]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) ...

  2. 子网划分和VLAN

    子网划分 IP地址的结构和分类 根据tcp/ip协议,连接在Internet上的每个设备都必须有一个IP地址,它是一个32位二进制数,为了方便人类识别,我们将它用点分十进制表示,每8位分为一段. IP ...

  3. 【事件中心 Azure Event Hub】使用Logstash消费EventHub中的event时遇见的几种异常(TimeoutException, ReceiverDisconnectedException)

    问题描述 使用EFK(Elasticsearch, Fluentd and Kibana)在收集日志的解决方案中, 可以先把日志发送到EventHub中,然后通过Logstash消费EventHub中 ...

  4. Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互

    引言 在与实现了语音合成.语义分析.机器翻译等算法的后端交互时,页面可以设计成更为人性化.亲切的方式.我们采用类似于聊天对话的实现,效果如下: 智能客服(输入文本,返回引擎处理后的文本结果) 语音合成 ...

  5. 【CF1436C】Binary Search 题解

    原题链接 题意简介 要求有多少种 n 的排列,能够通过二分法正确地找到放在 pos 处的数字 x. 答案对 1e9+7 取模.n<=1000. 采用的二分法如下图: 思路分析 首先,这个排列中有 ...

  6. Git高级使用教程

    Git 与 SVN 区别 Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的 ...

  7. onedrive同步其他任意文件夹

    经过多次尝试,成功同步其他文件夹内容到onedrive,最后那次尝试是成功的,前面是可能犯的错误.注意3点:1. 用管理员身份运行cmd:2. 路径有空格时用双引号括起来:3. /d后面接的第一个路径 ...

  8. 常用的实现Javaweb页面跳转的方式

    我们有两大种方式来实现页面跳转:1.JS(javascript):2.jsp跳转 先说jsp(金j三s胖p):1.转发:request.getRequestDispatcher("1.jsp ...

  9. 数据结构(C++)——链表

    顺序表和链表的比较 1.存取方式 顺序表可以随机访问,而链表只能从表头顺序查找.(因此经常查找顺序表某一个元素时,顺序表更适合) 2.逻辑结构与物理结构 顺序表中,逻辑上相邻的元素,其物理存储位置也相 ...

  10. Redis---06主从复制(薪火相传)

    一.什么是薪火相传模式 上一个slave(从机)是下一个slave(从机)的Master(主机) 二.为什么要这样 优点:从机同样可以接收其他从机的连接和同步请求,那么该从机作为了链条中下一个的主机, ...