取数游戏

 
【训练题】取数游戏
 
 
时间限制:1秒  内存限制:64M
 
   

 

 

 

 

【问题描述】

 

 


  帅帅经常跟同学玩一个取数游戏:对于一个给定的长度为n的整数序列,每个元素a[i]为非负整数。游戏规则如下:

  1、每次取数时须从取走一个元素,共取n次;
  2、每次取走的元素只能是当前序列的首或尾元素;
  3、每次取数都有一个得分值,取数的得分=被取走的元素值*2^i,其中i表示第i次取数(从1开始编号);
  4、游戏结束总得分为n次取数得分之和。

  帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

 

 

 

 

【输入格式】

 

 


  第一行一个整数n,表示整数序列的长度。
  第二行有n个用空格分开的非负整数,表示整数序列

 

 

 

 

【输出格式】

 

 


  一个整数,表示最大得分。

 

 

 

 

【输入样例】

 

 


4
4 5 0 5

 

 

 

 

【输出样例】

 

 


122

 

 

 

 

【数据范围】

 

 


  n<=20
  0<=a[i]<=1000


 

 

 

这道题是一道区间动规

按照顺序处理这道题十分困难,反正我是没做出来。正方向难,我们就反着来;

反着来,我们就从最后一个元素倒着取,然后取倒数第二个,然后倒数第三个。。。。

一道区间动规题,我们就可以设状态转移方程为f(i,j)表示第i个数到第j个数的能取出的最大值;

现在假如我们还剩下两个数没取,我们可以先取前面那个数,然后再取后面那个数;我们也可以先取后面那个数,再取前面那个数;

那么,状态转移方程就出来了  f(i,j)=MAX{ f(i+1,j)+取a[i]的值 , f(i,j-1)+取a[j]的值 }

关于取a[i]的值该怎么计算呢?现在我们计算的是区间[i,j]的值,那么区间[i,j]中有j-i+1个元素,那么已经取走了N-j+i-1个元素,所以说

a[i]就是第N-j+i个元素,那么取走a[i]的值就是a[i]*2^(N-j+i)

所以状态转移方程最后就写为 f(i,j)=MAX{ f(i+1,j)+a[i]*2^(N-j+i) , f(i,j-1)+a[j]*2^(N-j+i) }

 

边界:f(i,i)=a[i]*2^N;

最后答案:f(1,N);

 

易错点:这道题,不能按照顺序扫描i,j,而是要按照区间大小从小到大扫描,即区间长度为2的先扫,然后区间长度为3的,然后为4的。。。。仔细想想为什么

 

程序:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int N;
int a[25];
long long d[30][30];

long long mi(int x)
{
 long long ans=1;
 for(int i=1;i<=x;i++)
  ans*=2;
  return ans;
}

void Ready()
{
 scanf("%d",&N);
 for(int i=1;i<=N;i++)
  scanf("%d",&a[i]);
 memset(d,0,sizeof(d));
 for(int i=1;i<=N;i++)
  d[i][i]=a[i]*mi(N);
}

int MAX(int x,int y)
{
 return x>y ? x:y;
}

void Working()
{
 for(int i=1;i<N;i++)
  for(int j=1;j<=N && i+j<=N;j++)
   {
    d[j][i+j]=MAX(d[j+1][i+j]+a[j]*mi(N-i),d[j][i+j-1]+a[i+j]*mi(N-i));
   }
   cout<<d[1][N];
}

int main()
{
 Ready();
 Working();
 return 0;
}

 


by:重庆一中吴松隐

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值