Main » 2011 » November » 7 » 删数(解题报告+原程)
12:33 PM
删数(解题报告+原程)

【问题描述】
有 N 个不同的正整数数 x 1 , x 2 , ... x N 排成一排,我们可以从左边或右边去掉连续的 i 个数(只能从两边删除数), 1<=i<=n ,剩下 N-i 个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。
每次操作都有一个操作价值,比如现在要删除从 i 位置到 k 位置上的所有的数。操作价值为 |x i – x k |*(k-i+1) ,如果只去掉一个数,操作价值为这个数的值。
任务
如何操作可以得到最大值,求操作的最大价值。
Input Data
输入文件 remove.in 的第一行为一个正整数 N ,第二行有 N 个用空格隔开的 N 个不同的正整数。
Output Data
输出文件 remove.out 包含一个正整数,为操作的最大值
约束和提示
3<=N<=100 
N 个操作数为 1..1000 之间的整数。 
样例
remove.in

54 29 196 21 133 118
remove.out
768
说明:经过 3 次操作可以得到最大值,第一次去掉前面 3 个数 54 、 29 、 196 ,操作价值为 426 。第二次操作是在剩下的三个数( 21 133 118 )中去掉最后一个数 118 ,操作价值为 118 。第三次操作去掉剩下的 2 个数 21 和 133 ,操作价值为 224 。操作总价值为 426+118+224=768 。

题解:
本题为今天的考试题中最水的一道,哎,鄙人较水,没有写出来,(水呀!水呀!水呀水!),还是来好好总结一下思路吧!!!
首先这是一道动态规划,跟NOIP2007矩阵取数游戏略像,哎,先写一下动态转移方程:i表示从前面取i个,j表示从后面取j个,q[i][j]=max(q[k][j]+w[k+1][i],q[i][k]+w[n-j+1][n-k]),这题败在初始化了,伤不起呀,一定要把q[i][0]和q[0][j]的情况初始化了!!
原程:C++语言:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define max(a,b) ((a)>=(b)?(a):(b))
using namespace std;
int n,a[110],q[110][110],w[110][110];
int main()
{
    freopen ("remove.in","r",stdin);
    freopen ("remove.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        w[i][i]=a[i];
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=i+1;j<=n;j++)
        {
            w[i][j]=abs((double)(a[j]-a[i]))*(j-i+1);
        }
    }
    for (int i=1;i<=n;i++)
        q[i][0]=w[1][i];
    for (int i=1;i<=n;i++)
        q[0][i]=w[n-i+1][n];
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if (i+j>n)
            {
                continue;
            }
            int temp1=0;
            for (int k=0;k<=i;k++)
            {
                if (q[k][j]+w[k+1][i]>temp1)
                {
                    temp1=q[k][j]+w[k+1][i];
                }
            }
            int temp2=0;
            for (int k=0;k<=j;k++)
            {
                temp2=max(temp2,q[i][k]+w[n-j+1][n-k]);
            }
            q[i][j]=max(temp1,temp2);
        }
    }
    int answer=0;
    for (int i=1;i<=n;i++)
    {
        if (q[i][n-i]>answer)
        {
            answer=q[i][n-i];
        }
    }
    cout<<answer;
    return 0;
}


神牛飘过,水牛留步!
ORZ  CZB!!
Views: 333 | Added by: dandan | Tags: NOIP | Rating: 0.0/0
Total comments: 0
Name *:
Email *:
Code *: