码迷,mamicode.com
首页 > 其他好文 > 详细

【noip模拟】德充符

时间:2017-08-22 17:37:15      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:std   ctime   pen   ++   i++   答案   log   cti   序列   

时间限制:2s
内存限制:512MB

【题目描述】
申徒嘉和郑子产都是伯昏无人的学生,子产因为申徒嘉是残疾人,非常看不起他,于是
想要刁难他。
子产给了申徒嘉 n个数 a1,a2...an。
现在他要求申徒嘉重新排列这些数,使得 H=||...|b1-b2|-b3|-b4|-...|-bn|最大(b 是
a 重新排列后的序列,|x|表示取 x的绝对值)
申徒嘉对于吹逼很擅长,但是数学就不怎么样了,于是他请你来帮帮他。

【输入格式】
第一行一个数 n,接下来一行n个数,第 i 个数表示a[i]
n<=300
1<=a[i]<=300
对于30%的数据,n<=10

【输出格式】
输出一行一个整数表示答案

【样例输入】
4
3 6 7 8

【样例输出】
6

【样例解释】
对于第一组样例:
|||6-8|-3|-7| = 6

【题目分析】

 

乱搞做法:

 

因为答案不超过300,而且似乎要控制只有少数特定的排列使得答案最大是不太容易的,因此不断随机打乱更新答案,就很容易得到最大值。

 

 

 

标准做法:

 

考虑堆积木模型:

 

现在你有两个塔,初始高度都是0,n个积木,每个积木的高度是a[i],现在你每次可以选一个积木放到当前高度较矮的那个塔上,最大化最后两个塔的高度差

 

容易证明这个问题和原问题等价

 

现在考虑怎么解决这个问题,我们发现每次只能往较矮的那个塔上放积木这个限制非常麻烦。

 

不难证明最高的一个积木一定是最后放的(试想把最高的积木移到中间上,结果一定不会变优)

 

现在我们把最高的一个积木拿掉,这样问题就变成了最小化高度差

 

如果要最小化高度差的话,每次只能往较矮的那个塔上放积木这个条件是没有用的(要得到最后的最优解,一定存在一种方案是满足这个限制的)

 

因此就去掉了这个限制,接下来愉快地DP就好了。

 

设F[i][k]表示只用前i个,两边的高度差达到k可行不可行,转移:

 

转移:

 

if(f[i-1][k])

 

F[i][k+a[i]] = F[i][abs(k-a[i])] = true

【code】

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<vector>
using namespace std;

const int N = 305;
int n, a[N];

inline int read(){
    int i = 0, f = 1; char ch = getchar();
    for(; (ch < 0 || ch > 9) && ch != -; ch = getchar());
    if(ch == -) f = -1, ch = getchar();
    for(; ch >= 0 && ch <= 9; ch = getchar())
        i = (i << 3) + (i << 1) + (ch - 0);
    return i * f;
}

inline void wr(int x){
    if(x < 0) putchar(-), x = -x;
    if(x > 9) wr(x / 10);
    putchar(x % 10 + 0);
}

int main(){
    freopen("dcf.in", "r", stdin);
    freopen("dcf.out", "w", stdout);
    n = read();
    srand(time(0));
    for(int i = 1; i <= n; i++) a[i] = read();
    int T = 200000, ans = -1;
    while(T--){
        random_shuffle(a + 1, a + n + 1);
        int sum = a[1];
        for(int i = 2; i <= n; i++)
            sum = abs(sum - a[i]);
        if(sum > ans) ans = sum;
    }
    wr(ans);
    return 0;
}

 

【noip模拟】德充符

标签:std   ctime   pen   ++   i++   答案   log   cti   序列   

原文地址:http://www.cnblogs.com/CzYoL/p/7412531.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!