原题链接:https://www.acwing.com/problem/content/285/  

题意简单来说就是:给你一个环,断掉一条边使其成为一个链,用这个链跑dp,求最大得分。

首先这不是一道板子题。。。跟板子区别如下:

1.多了一重循环,最开始要求断掉一条边,但是我们不知道要断掉哪一条边,因此需要循环一遍来比较。

2.计算方法有加法有乘法,而且数据有正数有负数。这两个条件任意一个都不足惧,但是如果凑在一起。。。就很微妙了。

  何出此言?比如说,我们用 f [ i ] [ j ]来表示从i号点到j号点的最大得分。那么假如,最后一次的运算是乘法。你在最后一次计算的时候,用于相乘的两个数,肯定都是它们各自那个区间的最优解,也就是最大的。然而,假如说在这个过程中,你淘汰了一些负数的值,那就很危险了。比如,你最后选择了1000和100相乘,但是本来你可以让-10000和-3000相乘的,那不就直接gg了吗。。

  负负得正,真是麻烦。。。。

  那怎么解决呢?其实也简单。只要另开一个数组记录最小得分即可~~;

3.题目还要求: 有些边如果在首次移动中被删除,可以导致最高得分。在输出文件的第二行,要求列举出所有这样的边,而且按照升序输出,其间用一个空格分开。(这句话直接粘贴的),也就是说,我们需要用一个数组把每条边和断掉该条边所能获得的最大得分匹配起来,以便最后比较。

说的差不多了,上代码:

 1 #include <cstdio>
2 #include <algorithm>
3 #include <cmath>
4 #include <iostream>
5 #include <cstring>
6 using namespace std;
7 const int maxn=50+5,Inf=1e9+10;
8 int n,data[maxn<<1];//用来存储各点权;因为是环,所以左移一位;
9 int f[maxn<<1][maxn<<1][3];// f[i][j][1]表示从i号点到j号点的最大得分,f[i][j][2]表示从***到***的最小得分;
10 int ff[maxn<<1];//ff储存每条断边的最大得分,便于最后查找 ;
11 char c[maxn<<1]; //储存符号;
12 int q,w,e,r;//方便比较的变量。。
13 int ans_point=(-1)*Inf;//最大得分,先初始化为最小;
14 void Read(){
15 cin>>n;//因为有字符+空格的输入。。所以cin比较方便;
16 for(int i=1;i<=n;++i){
17 cin>>c[i]>>data[i];
18 c[i+n]=c[i];
19 data[i+n]=data[i];
20 }
21 }
22 void Solve(){
23 for(int i=1;i<=n;++i){//枚举断边,断边编号+n就是形成的链;
24 for(int j=1;j<=(n<<1);++j){//初始化;
25 for(int k=1;k<=(n<<1);++k){
26 f[j][k][1]=(-1)*Inf;//求最大值;
27 f[j][k][2]=Inf;//求最小值;
28 }
29 }
30 for(int j=1;j<=(n<<1);++j){//初始化区间dp;
31 f[j][j][1]=f[j][j][2]=data[j];
32 if(c[j+1]=='t') f[j][j+1][1]=f[j][j+1][2]=data[j]+data[j+1];
33 else f[j][j+1][1]=f[j][j+1][2]=data[j]*data[j+1];
34 }
35 for(int l=2;l<=n;++l){//枚举区间长度;
36 for(int j=i;j+l<=i+n;++j){//终止条件!!!小心出错;j是起点,k是终点;
37 int k=j+l-1;//把这里的l写成i了,找了半天错。。。吐了吐了;
38 for(int x=j;x<k;++x){//不可以等于k,因为有x+1;
39 if(c[x+1]=='t'){//读过题的都知道,c[x+1]连接的是x号节点和(x+1)号节点;
40 f[j][k][1]=max(f[j][k][1],f[j][x][1]+f[x+1][k][1]);
41 f[j][k][2]=min(f[j][k][2],f[j][x][2]+f[x+1][k][2]);
42 }else{
43 q=f[j][x][1]*f[x+1][k][1];
44 w=f[j][x][2]*f[x+1][k][2];
45 e=f[j][x][1]*f[x+1][k][2];
46 r=f[j][x][2]*f[x+1][k][1];
47 f[j][k][1]=max(f[j][k][1],max(max(q,w),max(e,r)));
48 f[j][k][2]=min(f[j][k][2],min(min(q,w),min(e,r)));
49 }
50 }
51 }
52 }
53 ff[i]=f[i][i+n-1][1];//注意是i+n-1不是i+n。。小学学的植树问题不要搞错;
54 }
55 for(int i=1;i<=n;++i){//因为可能有多个最大边,所以先把最大得分算出来,然后。。
56 ans_point=max(ans_point,ff[i]);
57 }
58 printf("%d\n",ans_point);//注意换行;
59 for(int i=1;i<=n;++i){//然后输出所有跟最大得分相等的边就行了;
60 if(ans_point==ff[i]) printf("%d ",i);//注意空格;
61 }
62 }
63 int main(){//芜湖,可怜的主函数,啥也没干;
64 Read();
65 Solve();
66 return 0;
67 }

最新文章

  1. LeetCode 396. Rotate Function
  2. Flex 文本控件实现自定义复制粘贴
  3. oralce之存储过程
  4. gradle编译出错:Execution failed for task &amp;#39;:app:compileTestDebugJava&amp;#39;.
  5. Look and say numbers
  6. Android从网络中获取xml文件并解析数据
  7. localStorage 的基本使用
  8. 处理jQuery append加入的元素 绑定事件无效的方法
  9. Spring MVC报错:The request sent by the client was syntactically incorrect ()
  10. Loadrunner11不能调用IE8解决方法大全
  11. web api 安全
  12. python之编程风格
  13. android 一些常用的功能方法代码块
  14. 使用CefSharp在.Net程序中嵌入Chrome浏览器(五)——Javascript交互
  15. Nginx-基础配置
  16. python反射,单例模式
  17. 【CodeForces】899 E. Segments Removal
  18. Transaction And Lock--在事务中使用TRY CATCH
  19. PHP-------ajax返回值 返回JSON 数据
  20. PHP的报错级别并返回当前级别error_reporting()

热门文章

  1. Throwable中3个异常的方法
  2. [CVE-2020-1956] Apache Kylin远程命令执行漏洞复现
  3. 硕盟SM-T54|type-c转接头HDMI+VGA+USB3.0+PD3.0四合一多功能扩展坞接口功能说明
  4. 使用python快速搭建http服务
  5. vue中如何深度监听一个对象?
  6. Python程序调用摄像头实现人脸识别
  7. css3 图片变黑白 filter
  8. 微信公众号jssdk分享接口onMenuShareAppMessage自定义的参数无效,微信分享失败原因
  9. JDBC-1(概述&amp;建立)
  10. Java基础系列(27)- 什么是方法