题意概括:
有 N 个人,每个人都佩戴一顶帽子(帽子种类有 1、2、3 … N );
接下来 N 个数表示所有人里面 与 第 i 个人佩戴了不同帽子的总数。
解题思路:
ai 代表与自己佩戴了不同帽子的个数,那么反过来意思就是说有 N - ai个人佩戴了与自己相同帽子。
如果能满足 数量为 ai 的 个数 Si == N - ai, 则说明刚好有 N-ai 个人佩戴相同帽子。
如果 Si > N-ai ,则需要判断 这 Si 个人里面能否内部平衡掉, 也就是分成若干块 N-ai,每一块佩戴不同的帽子,但是块内的人佩戴的帽子是相同的,这样也满足条件。
即 Si%(N-ai) ?= 0;
如果 Si % (N-ai) != 0 则说明无法平衡。
最后按块编号,输出答案。
tip:代码实现和细节很重要。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN = 1e5+10;
vector<vector<int> >num(MAXN);
int ans[MAXN];
int main()
{
int N, x;
scanf("%d", &N);
for(int i = 1; i <= N; i++){
scanf("%d", &x);
num[N-x].push_back(i);
}
int tp, no = 0;
bool flag = true;
for(int i = 1; i <= N; i++){
tp = num[i].size();
if(tp%i != 0){
flag = false;
break;
}
for(int j = 0; j < tp; j++){
if(j%i == 0) ++no;
ans[num[i][j]] = no;
}
}
if(flag){
puts("Possible");
for(int i = 1; i <= N; i++)
printf("%d ", ans[i]);
}
else{
puts("Impossible");
}
return 0;
}
题意:有n顶不同的帽子,现在给你n个数,ai表示第i个人说,有ai个人与自己的帽子不同,问你是否能求出一种解决方案,能的话,输出一组。
题解:这题ai表示第i个人说,有ai个人与自己的帽子不同,那么我们可以反过来看,就是说有n-ai个人与自己的帽子相同,我们先按帽子排序一下,最后输出时再按序号排序一下。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
int state;///说明有state个人的帽子与我相同
int type;///存储每个人帽子的类型
int id;///存储每个人的id
} num[100010];
bool cmp(node a,node b) ///
{
return a.state>b.state;
}
bool cmp1(node a,node b)
{
return a.id<b.id;
}
int book[100010];///book[i]表示记录i类型的帽子有多少个
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(book,0,sizeof(book));
for(int i=1; i<=n; i++)
{
scanf("%d",&num[i].state);
num[i].state=n-num[i].state; ///反过来
num[i].id=i;
}
sort(num+1,num+1+n,cmp); ///按帽子类型排
num[0].state=-1;
int item=1;
bool flag=true;
num[1].type=1; ///初始化
int sum=num[1].state-1;
for(int i=2; i<=n; i++) ///给每个人赋值帽子类型
{
if(sum>0)
{
num[i].type=item;
sum--;
}
else
{
num[i].type=++item;
sum=num[i].state-1;///换下一中类型
}
if(item>n)
{
printf("Impossible\n");
flag=false;
break;
}
}
if(flag)
{
bool flag2=true;
for(int i=1; i<=n; i++) ///判断此分配方案是否合法
{
int j=num[i].type;
book[j]+=1; ///记录每种类型的数量
}
for(int i=1; i<=n; i++)
{
if(num[i].state!=book[num[i].type]) ///如果不等,说明这方案不行了
{
flag2=false;
break;
}
}
if(flag2)
{
sort(num+1,num+1+n,cmp1); ///按id排序一下
printf("Possible\n");
for(int i=1; i<=n; i++)
printf("%d ",num[i].type);
puts("");
}
else
{
printf("Impossible\n");
}
}
}
return 0;
}