题目描述

多边形(Polygon)游戏是单人玩的游戏,开始的时候给定一个由N个顶点构成的多边形(图1所示的例子中,N=4),每个顶点被赋予一个整数值,而每条边则被赋予一个符号:+(加法运算)或者*(乘法运算),所有边依次用整数1到N标识。

图1:一个多边形的图形表示 首次移动(first move),允许将某条边删除; 接下来的每次顺序移动(subsequentmoves),包括下面步骤:

1、选出一条边E,以及由E联接的顶点V1和V2;

2、用一个新的顶点,取代边E及其所联接的两个顶点V1和V2。新顶点要赋予新的值,这个值是对V1和V2,做由E所指定的运算,所得到的结果。

所有边都被删除后,只剩下一个顶点,游戏结束。游戏的得分就是该顶点的数值。 下面是一个游戏实例: 考虑图1中的多边形。

玩家第一步删除第3条边。结果如图2所示。  图2 删除第3条边

之后,玩家删除第1条边  图3 删除第1条边

然后删除第4条边,  图4 删除第4条边

最后删除第2条边。得分是0.  图5 删除第2条边 任务: 编写一个程序,对于任意给定的多边形,计算可能的最高得分,并且列举出所有的可以导致最高得分的被首次移动的边。

输入格式

文件POLYGON.IN给出的是,由N个顶点构成的多边形。文件包括2行: 第一行记录的是数值N(n<=50); 第二行包含所有边(1,…,N)分别被赋予的符号,以及嵌入到两条边之间的顶点的数值(第一个整数值对应于与1号、2号边同时相连的顶点;第二个整数对应于与2号、3号边同时相连的顶点;…;等等。最后一个数值对应于与N号、1号边同时相连的顶点),符号和数值之间由一个空格分隔。边的符号有2种:字母t(对应于+),字母x(对应于*)。

输出格式

在文件POLYGON.OUT的第一行,你的程序必须输出在输入文件指定条件下可能得到的最高得分。 有些边如果在首次移动中被删除,可以导致最高得分。在输出文件的第二行,要求列举出所有这样的边,而且按照升序输出,其间用一个空格分开。

样例

样例输入

4
t -7 t 4 x 2 x 5

样例输出

33
1 2

数据范围与提示

样例输入对应于图1所示的多边形。第二行的第一个字符是1号边的符号。

此题类似石子合并,将环状多边形转换成链,由n转入2*n+1个字符。

总数量不能变,所以一点一点向后推移;

先进行一个循环,决定去掉那条边,再加n,向后推移;

f[i][j],表示从i到j的最优解;

每一个点必定是由两个点组成,so,在i,j区间枚举分割点,注意分割点不能等于j;

因为这题中,数字有正有负,必然要考虑负负得正的情况

例如,-1000*-1000=1000000 100*100=10000 而1000000>10000,但-1000却小于100;

所以每一次合并必然要考虑最小值和最大值;

如果下一次合并时,符号是‘+’,那就直接将最大值和最小值相加;

若是‘*’,那就将大*大,大*小,小*大,小*小四种比较一下,寻找最大值和最小值;

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int n,shu[150],f[150][150][3],sum[150][150],ff[150]={0},ma,mb,a,b,c,d;
char fu[150];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>fu[i]>>shu[i];//先输入符号,在输入数字
}
for(int i=n+1;i<=2*n;i++)
{
shu[i]=shu[i-n];
fu[i]=fu[i-n];
}
for(int i=1;i<=n;i++)
{
for(int o=1;o<=2*n;o++)
{
for(int p=1;p<=2*n;p++)
{
f[o][p][1]=-9999999;//求大值,初始化最小
f[o][p][2]=9999999;//求小值,初始化最大
}
}
for(int q=1;q<=2*n;q++)//初始化区间dp
{
f[q][q][1]=shu[q];
f[q][q][2]=shu[q];
if(fu[q+1]=='t')
{
f[q][q+1][1]=shu[q]+shu[q+1];
f[q][q+1][2]=shu[q]+shu[q+1];
}
if(fu[q+1]=='x')
{
f[q][q+1][1]=shu[q]*shu[q+1];
f[q][q+1][2]=shu[q]*shu[q+1];
}
}
for(int l=2;l<=n;l++)
{
for(int j=i;j<=i+n-l;j++)
{
int k=j+l-1;
for(int x=j;x<k;x++)//一定要小于k,因为后面有x+1;
{
if(fu[x+1]=='t'&&f[j][k][1]<f[j][x][1]+f[x+1][k][1])f[j][k][1]=f[j][x][1]+f[x+1][k][1];
if(fu[x+1]=='t'&&f[j][k][2]>f[j][x][2]+f[x+1][k][2])f[j][k][2]=f[j][x][2]+f[x+1][k][2];
if(fu[x+1]=='x')
{
a=f[j][x][1]*f[x+1][k][1];
b=f[j][x][2]*f[x+1][k][1];
c=f[j][x][1]*f[x+1][k][2];
d=f[j][x][2]*f[x+1][k][2];
f[j][k][1]=max(max(max(a,b),max(c,d)),f[j][k][1]);
f[j][k][2]=min(min(min(a,b),min(c,d)),f[j][k][2]);
}
}
}
}
ff[i]=f[i][i+n-1][1];
}
ma=-1000000;
for(int i=1;i<=n;i++)//寻找最大值
{
if(ma<ff[i])
{
ma=ff[i];
mb=i;
}
}
cout<<ma<<endl;
for(int i=1;i<=n;i++)
{
if(ff[i]==ma)
{
cout<<i<<" ";//输出可以断第几个
}
}
}
/*
4 120
x 2 x 3 x 4 x 5 1 2 3 4 6 10000
x -10 x -10 x -10 t 10 t 10 t 10 6 7 300000
x -10 x -10 x -10 x -10 t 10 t 10 t 10 5
以上是三组测试数据*/

以上是个人见解,,如有不妥请评论区发表意见

以下是改进后的代码

#include<bits/stdc++.h>
using namespace std;
int n,num[105],dp1[105][105],dp2[105][105],maxn[55],maxx;
char fu[105];
int main()
{
memset(dp1,0x8f,sizeof(dp1));
memset(dp2,0x3f,sizeof(dp2));
cin>>n;
for(int i=1;i<=n;i++){
cin>>fu[i]>>num[i];
fu[n+i]=fu[i];
num[n+i]=dp1[i][i]=dp1[n+i][n+i]=dp2[i][i]=dp2[n+i][n+i]=num[i];
}
for(int o=1;o<=n;o++){
for(int l=2;l<=n;l++){
for(int i=o;i<=o+n-l;i++){
int j=i+l-1;
for(int k=i+1;k<=j;k++){
int a,b,c,d;
if(fu[k]=='t'){
a=dp1[i][k-1]+dp1[k][j];
b=dp2[i][k-1]+dp2[k][j];
dp1[i][j]=max(dp1[i][j],a);
dp2[i][j]=min(dp2[i][j],b);
}
if(fu[k]=='x'){
a=dp1[i][k-1]*dp1[k][j];
b=dp1[i][k-1]*dp2[k][j];
c=dp2[i][k-1]*dp2[k][j];
d=dp2[i][k-1]*dp1[k][j];
dp1[i][j]=max(dp1[i][j],max(a,max(b,max(c,d))));
dp2[i][j]=min(dp2[i][j],min(a,min(b,min(c,d))));
}
}
}
}
maxn[o]=dp1[o][o+n-1];
maxx=max(maxx,dp1[o][o+n-1]);
}
cout<<maxx<<endl;
for(int i=1;i<=n;i++){
if(maxn[i]==maxx)
cout<<i<<" ";
}
}

多边形游戏——区间dp的更多相关文章

  1. 多边形游戏 /// 区间DP oj1903

    题目大意: ... Input 输入的第一行是单独一个整数n( 3 ≤ n ≤ 18 ),表示多边形的顶点数(同时也是边数). 接下来第n行,每行包含一个运算符("+"或" ...

  2. Vijos 1565 多边形 【区间DP】

    描述 zgx给了你一个n边的多边形,这个多边形每个顶点赋予一个值,每条边都被标上运算符号+或*,对于这个多边形有一个游戏,游戏的步骤如下:(1)第一步,删掉一条边:(2)接下来n-1步,每步对剩下的边 ...

  3. P1005 矩阵取数游戏[区间dp]

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.经过m次后 ...

  4. 圆桌游戏(区间DP)

    2.圆桌游戏 (game.cpp/c/pas) [问题描述] 有一种圆桌游戏是这样进行的:n个人围着圆桌坐成一圈,按顺时针顺序依次标号为1号至n号.对1<=i<=n的i来说,i号的左边是i ...

  5. BZOJ 2121: 字符串游戏 区间DP + 思维

    Description BX正在进行一个字符串游戏,他手上有一个字符串L,以及其他一些字符串的集合S,然后他可以进行以下操作:对 于一个在集合S中的字符串p,如果p在L中出现,BX就可以选择是否将其删 ...

  6. 洛谷 P1043 数字游戏 区间DP

    题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易.游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分 ...

  7. qscoj 喵哈哈村的打印机游戏 区间dp

    点这里去看题 区间dp ,dp[l][r][d]代表从l到r的区间底色为d,具体看代码 第一次见到区间dp...两个小时对着敲了五遍终于自己敲懂了一遍ac #include<bits/stdc+ ...

  8. 多边形游戏(DP)

    Description 多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形.每个顶点被赋予一个整数值,每条边被赋予一个运算符 "+" 或 "*". ...

  9. 【bzoj2121】字符串游戏 区间dp

    题目描述 给你一个字符串L和一个字符串集合S,如果S的某个子串在S集合中,那么可以将其删去,剩余的部分拼到一起成为新的L串.问:最后剩下的串长度的最小值. 输入 输入的第一行包含一个字符串,表示L. ...

随机推荐

  1. vue.js中使用set方法 this.$set

    vue教程中有这样一个注意事项: 第一种具体情况如下: 运行结果: 当利用索引改变数组某一项时,页面不会刷新.解决方法如下: 运行结果: 三种方式都可以解决,使用Vue.set.vm.$set()或者 ...

  2. 9.PHP文件处理

    PHP文件系统 (当成是扩展C++来看就行了,几乎一样): 读取整个文件readfile() .file(). file_get_contents() <?php    readfile('fi ...

  3. js中return;、return true、return false;区别

    一.返回控制与函数结果 语法为:return 表达式 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制 无函数结果,语法为:return; 在大多数情况下,为事件处理函数返 ...

  4. 记录数据库被攻击.md

    昨天的数据库还是正常的,早上想连接mysql,一直报错1045,最后才发现数据库被攻击了 navicat连接mysql疯狂报错1045 因为1045的报错,一般都是密码设置的问题,但是我怎么修改也没有 ...

  5. JVM核心技术(第一篇)

    目录 Java基础知识 一. 字节码技术 二.JVM类加载器 类的加载时机 三.JVM内存结构 四.JVM启动参数 4.1 系统属性参数 4.2 运行模式 4.3 堆内存 4.4 GC相关 4.5 分 ...

  6. MySQL连接本地服务器

    1.打开"控制面板" 2.搜索"管理工具",并点击第一个"管理工具" 3.双击"服务" 4.找到"MySQL& ...

  7. DirectX渲染时Clear无效的原因(造成叠影)

    最近在开发D3D程序的过程中,发现一件很奇怪的事情,就是在Render的时候,纹理总是留有"残影"(即上次Render后的帧):如上图,是一副纹理绕中心点旋转的向日葵,但是可以看到 ...

  8. Iterable 和 Iterator

    可以被for循环输出的为iterable (可迭代对象) 可以被next()调用并不断返回下一个数据的对象为iterator迭代器(python一切皆对象) 数据流,无法知晓其终点,只能推过next不 ...

  9. Jmeter(四十五) - 从入门到精通高级篇 - Jmeter之网页爬虫-上篇(详解教程)

    1.简介 上大学的时候,第一次听同学说网页爬虫,当时比较幼稚和懵懂,觉得就是几只电子虫子爬在网页上在抓取东西.后来又听说写代码可以实现网页爬虫,宏哥感觉高大上,后来工作又听说,有的公司做爬虫被抓的新闻 ...

  10. [bug] Job for network.service failed because the control process exited with error code

    原因 复制虚拟机,没有改网卡配置文件 参考 https://blog.csdn.net/dongfei2033/article/details/81124465