HDU5835 Danganronpa(简单推理)

来源:互联网 发布:知乎 dota2 编辑:程序博客网 时间:2024/06/05 10:06

HDU5835 Danganronpa(简单推理)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5835


题目

Time Limit: 1000MS Memory Limit: 65536KB
Description
Chisa Yukizome works as a teacher in the school. She prepares many gifts, which consist of n kinds with a[i] quantities of each kind, for her students and wants to hold a class meeting. Because of the busy work, she gives her gifts to the monitor, Chiaki Nanami. Due to the strange design of the school, the students’ desks are in a row. Chiaki Nanami wants to arrange gifts like this:

  1. Each table will be prepared for a mysterious gift and an ordinary gift.

  2. In order to reflect the Chisa Yukizome’s generosity, the kinds of the ordinary gift on the adjacent table must be different.

  3. There are no limits for the mysterious gift.

  4. The gift must be placed continuously.

She wants to know how many students can get gifts in accordance with her idea at most (Suppose the number of students are infinite). As the most important people of her, you are easy to solve it, aren’t you?

Input
The first line of input contains an integer T(T10) indicating the number of test cases.

Each case contains one integer n. The next line contains n (1n10) numbers: a1,a2,...,an, (1ai100000).

Output
For each test case, output one line containing “Case #x: y” (without quotes) , where x is the test case number (starting from 1) and y is the answer of Chiaki Nanami’s question.

Sample Input
1
2
3 2

Sample Output
Case #1: 2


题意

有n种礼物,第i个有ai个。现在要把他们分给一排同学,要求每个人发普通礼物和神秘礼物各一个,要求相邻两人的普通礼物不能为同一种,而神秘礼物随意,普通礼物和神秘礼物均从这n个礼物中选取。问最多能发给多少人。


分析

首先,贪心法模拟能过,但是时空复杂度就不理想了。
其实这题还可以用简单的推理完成,一个判断即可,0ms过题。下面给出思想。

首先,我们要去想办法将问题分成几个条件来转化后考虑。
情况1:我们考虑有无数量“绝对大”的礼物,绝对大即该种礼物的总数比其他种类的所有礼物的总数还要多。那么,能否发给多少人就与这个绝对大的礼物有关。先分配普通礼物:我们把其他礼物按间隔为1摆放,然后让绝对大的礼物去插空。然后多余的去填补神秘礼物,如果神秘礼物也能填补完,那么总数就为其他礼物数*2+1;如果填补不完,就从普通礼物后面截取然后往神秘礼物填,直到神秘和普通数量相同,总数为(其他礼物+总数最大的礼物个数)/2。如果不懂请见代码。
情况2:没有“绝对大”礼物,那么一定可以保证所有礼物排列后不存在相邻相同项(有兴趣的可以想办法证明)。那么总数就为总礼物数/2。


源码

#include<cstdio>#include<cstring>#include<iostream>#include<queue>#include<vector>#include<algorithm>#include<string>#include<sstream>#include<cmath>#include<set>#include<map>#include<vector>#include<stack>#include<utility>#include<sstream>#define mem0(x) memset(x,0,sizeof x)#define mem1(x) memset(x,-1,sizeof x)#define dbug cout<<"here"<<endl;//#define LOCALusing namespace std;typedef long long ll;typedef unsigned long long ull;const int INF = 0x3f3f3f3f;const int MAXN = 1e6+10;const int MOD = 1000000007;int a[20];int main(){    #ifdef LOCAL        freopen("C:\\Users\\asus-z\\Desktop\\input.txt","r",stdin);        freopen("C:\\Users\\asus-z\\Desktop\\output.txt","w",stdout);    #endif    int t;    scanf("%d", &t);    int n;    int kase = 0;    while(t--){        scanf("%d", &n);        ll sum = 0;        for(int i = 0; i < n; ++i){            scanf("%d", &a[i]);            sum += a[i];        }        sort(a, a+n);        int maxx = a[n-1];        sum -= maxx;        printf("Case #%d: ", ++kase);        if(maxx >= (((sum+1)+sum) + (sum+1)))            cout << sum*2+1 << endl;        else            cout << (sum+maxx)/2 << endl;    }    return 0;}
1 0