终于知道打算法赛的美妙之处了。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;
}