【动规】多边形游戏

做这个题的时候在网上并没有找到很好的实现代码,后来看《计算概论——程序设计阅读题解》(清华大学出版社),发现这是这本书的最后一题,实现得很好,于是加上自己的理解搬运过来分享。如果涉及侵权我会立即删除。
描述  

一个多边形,开始有n个顶点。每个顶点被赋予一个正整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。 
    现在来玩一个游戏,该游戏共有n步: 
    第1步,选择一条边,将其删除 
    随后n-1步,每一步都按以下方式操作:(1)选择一条边E以及由E连接着的2个顶点v1和v2; (2)用一个新的顶点取代边E以及由E连接着的2个顶点v1和v2,将顶点v1和v2的整数值通过边E上的运算得到的结果值赋给新顶点。 
    最后,所有边都被删除,只剩一个顶点,游戏结束。游戏得分就是所剩顶点上的整数值。那么这个整数值最大为多少?输入第一行为多边形的顶点数n(n ≤ 20),其后有n行,每行为一个整数和一个字符,整数为顶点上的正整数值,字符为该顶点到下一个顶点间连边上的运算符“+”或“*”(最后一个字符为最后一个顶点到第一个顶点间连边上的运算符)。输出输出仅一个整数,即游戏所计算出的最大值。

样例输入

4
4 *
5 +
5 +
3 +
样例输出

70

提示小规模问题可不必用动态规划方法编程求解,仅用递归就可以求解。
计算中不必考虑计算结果超出整数表达范围的问题,给出的数据能保证计算结果的有效性。
在给的例子中,计算过程为(3+4)*(5+5)=70。


设a[i][j]表示顶点i到顶点j-1之间(包含)所有如上述操作后得到的最大值,当j=i+1时,表示的就是点i的值,当j=i时,就是删除边(i-1,i)后得到的最大值。

我们的目标就是要求max{a[i][i]|i=0,1,2,...,n-1},即按照顶点i,i+1,...,n-1,...,j-1进行的游戏的最大值。


#include<stdio.h>
#define MAX 50
int main()
{
	int n,i,j,k,t,s,v,x,y,m;
	int a[MAX][MAX]={0};   //声明并初始化 
	char op[MAX],o;         
	scanf("%d",&n);
	for(i=0;i<n;i++)
		scanf("%d %c",&a[i][(i+1)%n],&op[(i+1)%n]); //这里得取模使形成一个环形链 
	for(t=2;t<=n;t++){          //t是步长,也就是下面i~j(实际上最后一个点是j-1)中包含点的个数 
		for(i=0;i<n;i++){       //i是起始点 
			j=(i+t)%n;          //实际上j-1是终止点,这里用j表示 
			for(s=1;s<t;s++){   //通过s和k将i~j-1分成两部分a[i][k]和a[k][j]注意a[i][k]是
				k=(i+s)%n;      //i到点k-1而不是到点k,那么在点k-1和点k中的操作符就是op[k] 
				x=a[i][k];
				y=a[k][j];
				o=op[k];
				v=(o=='+')?(x+y):(x*y); 
				if(v>a[i][j])    //比较大小,因为我们初始化a[MAX][MAX]是0,所以不必担心不符合规则 
					a[i][j]=v;
			}
		}
	}
	v=0;
	for(i=0;i<n;i++){         //现在我们找最大的值。你会问,上面我们并没有直接取a[i][i]呀? 
		if(a[i][i]>v)         //事实上当t=n时,我们就是在做这个操作,这时i=j,即这里的a[i][i] 
			v=a[i][i];
	}
	printf("%d\n",v);
	return 0;
 } 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值