HDU2208唉,可爱的小朋友

Problem Description
唉,小朋友是比较麻烦的。在一个幼儿园里,老师要上一节游戏课,有N个小朋友要玩游戏,做游戏时要用小皮球,但是幼儿园里只有M个小皮球,而且有些小朋友不喜欢和一些小朋友在一起玩,而只喜欢和另一些小朋友一起玩,比如傻妞只喜欢和傻瓜,傻根,傻蛋们一起玩,傻根又不喜欢和傻蛋一起玩,傻蛋喜欢和傻子一起玩。所以老师只好把他们分组,每个组至少有一个小球可以玩,而且每个组内不会有两个小朋友,相互不喜欢。现在给你这样一个幼儿园里小朋友之间关系的描述,做为老师,是否可以上好这节游戏课。

Input
数据有多个case,每个case先输入两个值N(1<=N<=10)和M(1<=M<=10),表示有N个小朋友(从0到N-1标号),和M个小皮球。接着有N行,第i行先输入一个K(0<=K<N),表示第i个小朋友有喜欢一起玩的其他小朋友的个数,然后后面有K个整数,表示K个小朋友的标号(不重复)。如果A喜欢和B一起玩,则B也喜欢和A一起玩,这个数据在输入时保证。两个case之间有空行

Output
对于每个case,如果老师可以上好课,输出YES,否则NO。

Sample Input
3 2
2 1 2
2 2 0
2 0 1

Sample Output
YES

在本题的评论区看到有个人的思路,我觉得挺好的,但是自己用C写一直WA,然后,提交了评论区这个人的答案,提示也有表达错误。实在是找不到错误,希望如果有人能找到错误,可以悄咪咪的告诉一下我呀! 哈哈哈!!!我终于找到了自己的错误!!!AC啦!!!
自己找到的错误:
1.visited[MAX]数组不小心定义为bool类型
2.dfs函数的if语句里,visited[v]不小心写成了visited[i]

具体思路就是:
有m个小皮球和n个小朋友,小朋友是0~N-1号。
1.把每个小皮球看成一组,通过小皮球来进行递归遍历。
2.假设我们成功地把v号小朋友放进1号小皮球组,然后再进入一次dfs,把v+1号小朋友放进1号小皮球组,如果v+1号小朋友不能放进1号小皮球组,就把v+1号小朋友放进2号小皮球组,……,如果前面都失败了,就退回来,把v号小朋友放进2号小皮球组,直到如果找到了一个满足的方式,就返回true,否则如果所有情况都不成立,就返回false。

#include<stdio.h>
#include<string.h>
#define MAX 11
int n,m;
bool map[MAX][MAX];
int visited[MAX];//第i号小朋友进的组号 
bool check(int v,int tag)//第v号小朋友想进第tag组 
{
	for(int i=0;i<n;i++) 
		if(i!=v&&visited[i]==tag&&map[v][i]==false)//i号小朋友玩tag号球,但是i号小朋友不喜欢v号小朋友
			return false;	
	return true; 
}
bool dfs(int v)
{ 
	if(v>=n) //n个小朋友都有组了,递归结束,找到了可以找的答案 
		return true;
	else
	{
		for(int i=1;i<=m;i++)//选择每个皮球作为分组 
		{
			if(visited[v]==0&&check(v,i))//判断v号小朋友是否可以进i号皮球组 
			{
				visited[v]=i;//加入第i组 
				if(dfs(v+1))//看看后面的小盆友可不可以成功 
					return true;
				visited[v]=0;//没有成功,那么就不加入第i组
			}
		}
	}
	return false;
} 
int main()
{
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		memset(map,false,sizeof(map));//false表示假设他们直接不喜欢一起玩
		memset(visited,0,sizeof(visited));
		int k,like;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&k);
			for(int j=0;j<k;j++)
			{
				scanf("%d",&like);
				map[i][like]=true;
				map[like][i]=true;
			}
		}
		if(m>=n)//球的数量大于等于小孩的数量,肯定可以玩 
			printf("YES\n");
		else
		{
			if(dfs(0))
				printf("YES\n");
			else printf("NO\n");
		}
	}
}

贴一个测评数据:
6 2
3 1 4 5
3 0 2 3
2 1 3
2 1 2
2 0 5
2 0 4

YES

再贴一个我最开始的时候的错误写法,很容易看出,如果按照我下面的思路,下面的这张图就会出现这样的错误答案(其中一个颜色的圈圈代表一组):
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#define MAX 11
int n,m;
bool map[MAX][MAX];
int visited[MAX];//0表示没有找过,其他数字表示玩第i号球
int tag;//标记目前是第i号球 
bool check(int v)
{
	for(int i=0;i<n;i++)
		if(visited[i]==tag&&map[v][i]==false)//i号小朋友玩tag号球,但是i号小朋友不喜欢v号小朋友
			return false;
	return true; 
}
void dfs(int v) 
{
	visited[v]=tag;
	for(int i=0;i<n;i++)
		if(!visited[i]&&check(i))
			dfs(i);
}
int main()
{
	while(scanf("%d %d",&n,&m)!=EOF)
	{
		memset(map,false,sizeof(map));//false表示假设他们直接不喜欢一起玩
		int k,like;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&k);
			for(int j=0;j<k;j++)
			{
				scanf("%d",&like);
				map[i][like]=true;
			}
		}
		int cnt=0;
		tag=0;
		memset(visited,0,sizeof(visited));
		for(int i=0;i<n;i++)
			if(visited[i]==0)
			{
				cnt++; 
				tag++; 
				dfs(i); 
			}
		if(cnt<=m)
			printf("YES\n");
		else printf("NO\n"); 
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值