您的位置:首页 > 其它

2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest A Toda2 贪心

2016-10-30 21:19 351 查看
/*
题目描述:给出n个人的分数,每轮选出2~5个人,把他们的分数减1,现要求把所有人的分数全部变成t,要求t最大,
输出每一轮选人的策略。

思路:注意两个性质:
1、每轮选2个或3个人,因为如果有一轮选了4个人,可以分成两轮每轮选两个人;如果有一轮选了5个人,可
以分成两轮,一轮选2个人,一轮选3个人
2、如果最终所有人的分数是t(即保证t是可以实现的分数的前提下),所有人初始时的分数总和是sum,那
么sum-n*t如果是偶数的话,一定可以通过每一轮选两个人来实现;如果是奇数的话,一定可以通过有一轮
选3人,其余每轮选两人来实现。
*/
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e2 + 5 ;
int ans[maxn * maxn][maxn] , r[maxn] , n ;
struct node
{
int val , num ;
bool operator<(const node & rhs)const
{
return val < rhs.val ;
}
};
int solve(int x)
{
mem(ans ,0) ;
priority_queue<node>Q;
int sum = 0;
for(int i = 1 ; i<= n ; i++){
node st = {r[i] - x , i} ;
if(st.val != 0){
sum += st.val ;
Q.push(st) ;
}
}
int cnt = Q.size() , cur = 1 ;
node y[4] ;
if(sum & 1){
if(cnt < 3)   return 0;
for(int i = 1 ; i <= 3 ; i++){
y[i] = Q.top();
--y[i].val ;
++ans[cur][y[i].num];
Q.pop();
}
for(int i = 1 ; i<= 3 ; i++){
if(y[i].val != 0){
Q.push(y[i]);
}
}
++cur;
}
while(!Q.empty()){
for(int  i = 1 ; i<= 2 ; i++){
y[i] = Q.top();
Q.pop();
++ans[cur][y[i].num];
--y[i].val ;
}
for(int i = 1 ; i<= 2 ; i++){
if(y[i].val != 0){
Q.push(y[i] ) ;
}
}
++cur;
if(Q.size() == 1)
return 0 ;
}
return (cur - 1 ) ;
}
int main()
{
while(scanf("%d",&n)!=EOF){
int maxv = -1 , minv = INF , tag = 0 ;
for(int i = 1 ; i<= n ; i++){
scanf("%d",&r[i]);
if(i >1 && r[i] != r[i-1])      tag = 1;
minv = min(minv , r[i]) ;
maxv = max(maxv , r[i]) ;
}
if(!tag){
printf("%d\n0\n",r[1]);
continue ;
}
int flag = 0 , res , t ;
for(int i = minv ; i > 0  ; --i){
if(t = solve(i)){
flag = 1 ;
res = i ;
break;
}
}
if(!flag){
printf("%d\n%d\n", 0 , n * maxv);
for(int i = 1 ; i<= n ; i++){
for(int j = 1 ; j<= maxv ; j++){
for(int k = 1 ; k <= n ; k++){
if(k == 1 || k == 2 || k == i)
printf("1");
else
printf("0");
}
printf("\n") ;
}
}
}
else{
printf("%d\n%d\n",res , t );
for(int i = 1 ; i<= t ; i++){
for(int j = 1 ; j<= n ; j++){
printf("%d",ans[i][j]);
}
printf("\n") ;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐