题目链接:http://poj.org/problem?id=1179

Time Limit: 1000MS Memory Limit: 10000K

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

  1. 4
  2. t -7 t 4 x 2 x 5

Sample Output

  1. 33
  2. 1 2

题意:

给出一个由无向边和节点组成的环,每个节点上有一个数字,每条边上有一个运算符(加或乘),

现在先割断一条边,然后环就成为一个链,然后你每次可以将这条链上的一条边缩成一个点,产生的新点的权值就是两个节点配合边运算所产生的结果。

不停地缩边成点,直到最后只有一个点为止,求这个点的权值最大是多少。

并给出所有能产生这个最大值的首先割断的边的编号,要求从小到大输出。

题解:

区间DP,周赛上wyb出的毒瘤题,每次两个小区间合并的时候,要记得有可能两个最小的负数相乘可能会产生正数最大值。

因此需要同时维护区间最小值和最大值。

AC代码:

  1. #include<cstdio>
  2. #include<vector>
  3. #include<algorithm>
  4. using namespace std;
  5. typedef pair<int,int> pii;
  6. const int INF=0x3f3f3f3f;
  7. const int maxn=;
  8.  
  9. int n;
  10. int op[*maxn],nm[*maxn];
  11. pii dp[*maxn][*maxn];
  12. inline int calc(int type,int a,int b){return type?a*b:a+b;}
  13. inline void updatemn(int &x,int y){if(x>y) x=y;}
  14. int solve(int l,int r)
  15. {
  16. for(int s=;s<=r-l+;s++)
  17. {
  18. for(int st=l,ed=st+s-;ed<=r;st++,ed++)
  19. {
  20. dp[st][ed].first=-INF;
  21. dp[st][ed].second=INF;
  22. for(int mid=st+;mid<=ed;mid++)
  23. {
  24. pii le=dp[st][mid-];
  25. pii ri=dp[mid][ed];
  26.  
  27. int tmp1=calc(op[mid],le.first,ri.first);
  28. dp[st][ed].first=max(dp[st][ed].first,tmp1);
  29. dp[st][ed].second=min(dp[st][ed].second,tmp1);
  30.  
  31. int tmp2=calc(op[mid],le.first,ri.second);
  32. dp[st][ed].first=max(dp[st][ed].first,tmp2);
  33. dp[st][ed].second=min(dp[st][ed].second,tmp2);
  34.  
  35. int tmp3=calc(op[mid],le.second,ri.first);
  36. dp[st][ed].first=max(dp[st][ed].first,tmp3);
  37. dp[st][ed].second=min(dp[st][ed].second,tmp3);
  38.  
  39. int tmp4=calc(op[mid],le.second,ri.second);
  40. dp[st][ed].first=max(dp[st][ed].first,tmp4);
  41. dp[st][ed].second=min(dp[st][ed].second,tmp4);
  42. }
  43. }
  44. }
  45. return dp[l][r].first;
  46. }
  47. int main()
  48. {
  49. scanf("%d",&n);
  50. for(int i=;i<n;i++)
  51. {
  52. int m; char o[];
  53. scanf("%s",o); op[i]=op[n+i]=(o[]=='x');
  54. scanf("%d",&m); nm[i]=nm[n+i]=m;
  55. }
  56.  
  57. for(int i=;i<*n;i++) dp[i][i]=make_pair(nm[i%n],nm[i%n]);
  58. int ans=-INF;
  59. for(int c=;c<n;c++) ans=max(ans,solve(c,c+n-));
  60.  
  61. vector<int> E;
  62. for(int c=;c<n;c++) if(dp[c][c+n-].first==ans) E.push_back(c+);
  63. sort(E.begin(),E.end());
  64. printf("%d\n",ans);
  65. for(int i=;i<E.size();i++) printf("%d%c",E[i],(i==E.size()-)?'\n':' ');
  66. }

数据:

  1. x x t t x
  2.  
  3. x - t - t - t - x -
  4.  
  5. t x t -
  6.  
  7. x t x t t x x x x x x t t x t x x t x x t x x x x x t x x x
  8.  
  9. x x x x - t x - x - x t t - x t x x t x x - x - x x t x t x x x t x x x x x x x - t x x - x - t x t x x x - t t - t - x

POJ 1179 - Polygon - [区间DP]的更多相关文章

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

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

  2. POJ 2995 Brackets 区间DP

    POJ 2995 Brackets 区间DP 题意 大意:给你一个字符串,询问这个字符串满足要求的有多少,()和[]都是一个匹配.需要注意的是这里的匹配规则. 解题思路 区间DP,开始自己没想到是区间 ...

  3. poj 1179 Polygon

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

  4. POJ 1160 经典区间dp/四边形优化

    链接http://poj.org/problem?id=1160 很好的一个题,涉及到了以前老师说过的一个题目,可惜没往那上面想. 题意,给出N个城镇的地址,他们在一条直线上,现在要选择P个城镇建立邮 ...

  5. IOI1998 Polygon [区间dp]

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

  6. POJ 1390 Blocks(区间DP)

    Blocks [题目链接]Blocks [题目类型]区间DP &题意: 给定n个不同颜色的盒子,连续的相同颜色的k个盒子可以拿走,权值为k*k,求把所有盒子拿完的最大权值 &题解: 这 ...

  7. poj 2955"Brackets"(区间DP)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题意: 给你一个只由 '(' , ')' , '[' , ']' 组成的字符串s[ ], ...

  8. POJ 1159 Palindrome(区间DP/最长公共子序列+滚动数组)

    Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 56150   Accepted: 19398 Desc ...

  9. HOJ 1936&POJ 2955 Brackets(区间DP)

    Brackets My Tags (Edit) Source : Stanford ACM Programming Contest 2004 Time limit : 1 sec Memory lim ...

随机推荐

  1. android下使用tcpdump抓包

    tcpdump是linux下的抓包工具,在android中没有,需要下载对应的工具. 下载地址:https://www.androidtcpdump.com/android-tcpdump/downl ...

  2. SNF快速开发平台--多组织+多平台+多系统处理方案

    多组织架构的集团要看组织的组成形式: 1.如果每个组织都是独立法人,这个相对来说简单一些,组织之间的关联交易跟集团外部客户交易没什么本质区别, 各个公司都是独立核算,正常的应收应付都需要开发票,各自出 ...

  3. How can R and Hadoop be used together?

    Referer: http://www.quora.com/How-can-R-and-Hadoop-be-used-together/answer/Jay-Kreps?srid=OVd9&s ...

  4. 最简单的基于FFmpeg的AVfilter样例(水印叠加)

    ===================================================== 最简单的基于FFmpeg的AVfilter样例系列文章: 最简单的基于FFmpeg的AVfi ...

  5. python 列表排序方法sort、sorted技巧篇

    Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. 1)排序基础 简单的升序排序是非常容易的.只需要调用sorte ...

  6. 【Jetty】Jetty 的工作原理以及与 Tomcat 的比较

    Jetty 应该是目前最活跃也是很有前景的一个 Servlet 引擎.本文将介绍 Jetty 基本架构与基本的工作原理:您将了解到 Jetty 的基本体系结构:Jetty 的启动过程:Jetty 如何 ...

  7. SpringBoot普通类中如何获取其他bean例如Service、Dao(转)

    工具类 import org.springframework.beans.BeansException; import org.springframework.context.ApplicationC ...

  8. 教你一招:使用最快速的方式激活windows10专业版

    1.安装win10专业版 2.在桌面新建“文本文档.txt” 3.复制如下代码到新新建的“文本文档.txt”中 slmgr /ipk VK7JG-NPHTM-C97JM-9MPGT-3V66T slm ...

  9. MSM8953 audio dts 代码跟踪

    跟一下msm8953音频的dts. msm8953-audio-mtp.dtsi &int_codec { status = "okay"; qcom,model = &q ...

  10. linux命令后加一个 &

    默认情况下,进程是在前台运行的,这时就把shell给占据了,我们无法进行其它操作.对于那些没有交互的进程,很多时候,我们希望将其在后台启动,可以在启动参数的时候加一个'&'实现这个目的. ti ...