CD 20 打气球的最大分数

题目描述
给定一个数组arr,长度为n。代表排有分数的气球。 每打爆一个气球都能获得分数,假设打爆气球的分数为X,获得分数的规则如下:
1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为R.获得分数为LXR
2)如果被打爆的气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边所有气球都已经被打爆,获得分数为LX。
3)如果被打爆气球的左边所有的气球都已经被打爆:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球。获得分数为X
R.
4)如果被打爆气球的左边和右边所有的气球都已经被打爆。获得分数为X。
目标是打爆所有气球,获得每次打爆的分数。通过选择打爆气球的顺序,可以得到不同的总分,请返回能获得的最大分数。
输入描述:
输出包括两行,第一行包括一个整数n(0<=n<=500),第二行包括n个整数,代表数组arr (1<=arr[i]<=100)。
输出描述:
输出包括一个整数,代表可能获得的最大分数。
示例1
输入
复制
3
3 2 5
输出
复制
50
说明
2->1->3 325+3*5+5=50
示例2
输入
复制
8
23 4 45 65 23 43 54 56
输出
复制
639019

 #include<iostream>
 #include<stdio.h>
 #include<algorithm>
 using namespace std;
 
 typedef long long ll;
 int arr[507];
 ll dp[507][507];//从i到j的最大分数   
 int main()
 {
 	int n;
 	scanf("%d",&n);
 	for(int i=1;i<=n;i++)
	   scanf("%d",&arr[i]);
	arr[0]=1 , arr[n+1]=1;
 	
 	for(int i=1;i<n;i++)
	 	dp[i][i]= arr[i]*arr[i-1]*arr[i+1];
 	
 	if(n==1)//特判 
     {
         cout<<arr[n]<<endl;
         return 0;
     }
 	
 	
 	
 	for(int i=n;i>0;i--)
	 {
	 	for(int j=i+1;j<=n;j++)
		 {
		 	//最后打左边
			 
			 dp[i][j]= dp[i+1][j] + arr[i]*arr[i-1]*arr[j+1];
			 //打右边或左边 
			 dp[i][j]= max( dp[i][j] , dp[i][j-1] +arr[j]*arr[i-1]*arr[j+1]   ) ;
			 
			for(int z=i+1;z<j;z++)
			{
				dp[i][j]= max( dp[i][j] , dp[i][z-1] + dp[z+1][j] + arr[z]*arr[i-1]*arr[j+1]   );
			}
		 }
	 }
	 
//	 for(int i=1;i<=n;i++)
//	 {
//	 	for(int j=1;j<=n;j++)
//	 	  cout<<dp[i][j]<<"  ";
//	 	cout<<endl;
//	 }
	 
	 cout<<dp[1][n]<<endl;
 	
 	return 0;
 }

代码优化

 #include<iostream>
 #include<stdio.h>
 #include<algorithm>
 using namespace std;
 
 typedef long long ll;
 int arr[507];
 ll dp[507][507];//从i到j的最大分数   
 int main()
 {
 	int n;
 	scanf("%d",&n);
 	for(int i=1;i<=n;i++)
	   scanf("%d",&arr[i]);
	arr[0]=1 , arr[n+1]=1;
 	
 	for(int i=1;i<n;i++)
	 	dp[i][i]= arr[i]*arr[i-1]*arr[i+1];
 	
 	if(n==1)//特判 
     {
         cout<<arr[n]<<endl;
         return 0;
     }
 	for(int i=n;i>0;i--)
	 {
	 	for(int j=i+1;j<=n;j++)
		 {
			for(int z=i;z<=j;z++)
			{
				dp[i][j]= max( dp[i][j] , dp[i][z-1] + dp[z+1][j] + arr[z]*arr[i-1]*arr[j+1]   );//当 z-1<i 或 z+1>j 是dp默认为0,可以减少代码量 
			}
		 }
	 }
	 cout<<dp[1][n]<<endl;
 	return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值