2019 BUPT Winter Training #1 div2 C - C//CodeForces - 1009B

终于知道打算法赛的美妙之处了。C题卡了好几天,从第一组数据错到第四组数据错,再到第43组数据卡了大半天,检查出来一个逻辑问题,最后AC。看到Status里变绿的那一刹那真的有一种无与伦比的快乐。
过题一时爽,一直过题一直爽,老不过题老不爽,不爽最后难收场。
题目开始那个distinct我老不明白啥意思,元素怎么变得“adj.明显的,清楚的; 卓越的……”。后来才看到“有区别的”,意思是同一种元素的涂色方案要不一样。
参考文献:
贫僧不打码 codeforces1102/B(思维题)
memset真的要慎用!!!!!
回到题目,这题目太抽象了,所有没有实例的,一律当狗来处理。
你要给n条狗上m种颜色,并且要满足:
1.每一条狗都要上色
2.每一种颜色都要用到
3.同一品种的狗要上不同的颜色(这样才是“有区别的”)
不同品种的狗没有约束

接下来会输入
狗的数量,颜色的数量
狗的品种代号(代号相同的狗就是同一品种的)

答案不唯一,如果有就输出YES并打印一种给每条狗涂色的方案,没有就打印NO。

思路:
1.首先是YES还是NO取决于某一品种的狗会不会比颜色数还多,如果有的话,根据抽屉原理一定会有两条狗同色,就不存在,反之存在。所以用dogs[n]来记录输入,即每条狗的品种,cnt[n]来记录某一品种的狗的数量。
2.先让每一种颜色都被使用一次,如果
①这个品种的狗没用过这个颜色(必须的)
②这种颜色还没被用过
③所有的颜色还没被用完
就上色并记录
3.所有的颜色都被用过一次了,剩下的狗只要
①同一品种的狗没用过这种颜色
即可。

注意品种号的范围是不定的,是底下的输入给定的,给出的范围是<=5000,所以数组的范围给了5005
在找出各品种号中最多的狗的数量,应当遍历所有的品种号

注意颜色是从1开始计数的,遍历范围是[1,m],狗的范围是[0,n-1],品种号的范围不知道,但一定是[0,5000]的子集
memset和我注释掉的代码的效果是一样的。而且memset最好只用来置0。使用前要#include <string.h>或者<memory.h>

#include <iostream>
#include <string.h>
#define N 5005
#define M 5005
int dogs[N];//记录每条狗的品种号
int cnt[N];//记录每个品种的狗的个数
bool isColorUsed[M];//标志某一种颜色是否使用过
bool isEleUsedColor[N][M];
//标志某一品种的狗是否使用过某一种颜色,如果5号品种的狗使用了2号颜色,isEleUsedColor[5][2]就要改为true
int ans[N];//记录最终的结果,即每一条狗的涂色
using namespace std;

void init()
{
	/*for(int i=0;i<N;i++) 
		cnt[i]=0;
	for(int i=0;i<M;i++)
		isColorUsed[i]=false;
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
			isEleUsedColor[i][j]=false;
	*/
	memset(cnt,0,sizeof(cnt));
	memset(isColorUsed,0,sizeof(isColorUsed));
	memset(isEleUsedColor,0,sizeof(isEleUsedColor));
}

int main(int argc, char const *argv[])
{
		int n,m;
		cin>>n>>m;
		init();//初始化,将cnt,isColorUsed和isEleUsedColor全部初始化为0(或false)
		for(int i=0;i<n;i++)
			{
				cin>>dogs[i];
				cnt[dogs[i]]++;
			}//读入每条狗,并记录每个品种的狗数量
		int max_cnt=0;
		for(int i=0;i<N;i++)//注意上界是N,不是n,N才是品种号范围
			if(cnt[i]>max_cnt)
				max_cnt=cnt[i];//找出所有品种中最多的狗数量
		if(m<max_cnt) {cout<<"NO"<<endl;return 0;}//如果颜色不够,直接打印NO,结束
		int color_cnt=0;//计数被使用过至少一遍的颜色数量
		for(int i=0;i<n;i++)//遍历狗
			for(int j=1;j<=m;j++)//颜色的范围是[1,m]
			{
				if(!isEleUsedColor[dogs[i]][j]&&//这一品种的狗没用过这种颜色
					!isColorUsed[j]&&//这种颜色没用过
					color_cnt<m)//所有的颜色还没用完
				{
					isEleUsedColor[dogs[i]][j]=true;//这一品种的狗使用了这一颜色
					isColorUsed[j]=true;
					color_cnt++;
					ans[i]=j;//序号为i的狗使用了j号颜色
					break;//已经找到了,不用再找了
				}
				if(color_cnt==m&&//所有的颜色都被用过一遍了
					!isEleUsedColor[dogs[i]][j])//这一品种的狗没用过这一颜色
				{
					isEleUsedColor[dogs[i]][j]=true;
					ans[i]=j;
					break;
				}
			}
		cout<<"YES"<<endl;
		for(int i=0;i<n;i++)
			{
				cout<<ans[i];
				if(i==n-1) cout<<'\n';
				else cout<<' ';
			}
		return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值