多边形游戏

 

最近在做DP,把一些做过的发上来。有些比较水,我又写得丑,所以大牛们尽管笑而不语,如果能提些宝贵一件,小弟更加感激不尽。

 

题目 - 多边形游戏

 
来源POJ
描述
多边形游戏是一种在一个具有n个顶点的多边形上进行的游戏。如图1是一个n=4对应多边形,每个顶点上都有一个整数,每条边都有一个运算符+或者*,所有边按从1到n进行编号。
多边形游戏(DP)
游戏都首先移除一条边,接下来可以进行如下操作:选择一条边E和与之相关联的点V1和V2,用一个新的点替换它们,新点上的整数为V1,V2上的整数用E上的操作符运算后的结果。
没有边时游戏结束,游戏得分就是最后剩下的那个顶点上的整数。
对于图1中的多边形,如果游戏者首先去掉3,然后依次去掉1、4、2,最后得分将是0。
多边形游戏(DP)
请你写一个程序,对于给定的多边形,计算出可能得到的最高分,并列出第一步移除哪些边可以得到这个最高分。
关于输入
输入第一行是一个正整数n(3<=n<=50),表示多边形的边数。
接下来一行是这个多边形的描述,包含n条边和n个顶点,加号边用t表示,乘号边用x表示,顶点用顶点上标的整数表示,输入按照边的编号从1到n的顺序给出。
关于输出
第一行输出可能得到的最高分。
第二行输出一些边的列表,只有第一步移除的边在这个列表中才可能得到最高分。每条边都用这个边上的编号表示,列表必须是升序的。
例子输入
4 
t -7 t 4 x 2 x 5 
例子输出
33 
1 2 

思路:

1、对每种第一次去掉的边进行打表

2、由于负负得正,所以你不能只算最大值。也就是说要计算多边形上连续的一段所能达到的最小值和最大值.

 

代码:

#include<iostream> 
using namespace std; 
 int main() 
 { 
 int n; 
 char ope[50],tope[50]; 
 int num[50],tnum[50]; 
 int maxresult[50][50][50]; 
 int minresult[50][50][50]; 
 int i,j,k,l; 
 int temp1,temp2; 
 int min,max; 
 int choice[50]; 
 cin>>n; 
 for(i=0;i<2*n;i++) 
 { 
 if(i%2 == 0) 
 cin>>ope[i/2]; 
 else 
 cin>>num[(i-1)/2]; 
 } 
 memset(maxresult,-999999,sizeof(maxresult)); 
 memset(minresult,999999,sizeof(minresult)); 
 for(i=0;i<n;i++) 
 { 
 for(j=0;j<n;j++) 
 { 
 tope[j]=ope[(i+1+j)%n]; 
 tnum[j]=num[(i+j)%n]; 
 } 
 for(j=0;j<n;j++) 
 { 
 maxresult[i][j][j]=tnum[j]; 
 minresult[i][j][j]=tnum[j]; 
 } 
 for(j=1;j<=n-1;j  
 { 
 for(k=0;k+j<=n-1;k++)  
 { 
 for(l=k;l<k+j;l++)  
 { 
 if(tope[l] == 't') 
 temp1 = maxresult[i][k][l]+maxresult[i][l+1][k+j]; 
 temp2 = minresult[i][k][l]+minresult[i][l+1][k+j]; 
 } 
 else 
 { 
 temp1 = maxresult[i][k][l]*maxresult[i][l+1][k+j]; 
 temp2 = minresult[i][k][l]*minresult[i][l+1][k+j]; 
 } 
 if(temp1>maxresult[i][k][k+j]) 
 maxresult[i][k][k+j]=temp1; 
 if(temp2>maxresult[i][k][k+j]) 
 maxresult[i][k][k+j]=temp2; 
 if(temp1<minresult[i][k][k+j]) 
 minresult[i][k][k+j]=temp1; 
 if(temp2<minresult[i][k][k+j]) 
 minresult[i][k][k+j]=temp2; 
 } 
 } 
 } 
 } 
 max=-999999; 
 j=0; 
 for(i=0;i<n;i++) 
 { 
 if(maxresult[i][0][n-1] > max) 
 { 
 max=maxresult[i][0][n-1]; 
 j=0; 
 choice[j++]=i+1; 
 } 
 else if(maxresult[i][0][n-1]==max) 
 choice[j++]=i+1; 
 } 
 cout<<max<<endl; 
 k=j; 
 for(j=0;j<k-1;j++) 
 cout<<choice[j]<<" "; 
 cout<<choice[k-1]<<endl; 
 return 0; 
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值