您的位置:首页 > 其它

hdu5506

2015-10-22 20:27 211 查看


GT and set

 
 Accepts: 35
 
 Submissions: 194

 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)

问题描述
有NN个集合,每个集合中有A_iA​i​​个数。
你要将这NN个集合划成LL个部分,使得每个部分的集合至少有一个共有的数。
如果至少有一个解输出YESYES,否则输出NONO

输入描述
第一行一个数T表示数据组数。(TT\leq≤2020)

对于每一组数据:
第一行两个数NN和LL。
接下来NN行每行描述一个集合:
第一个数A_iA​i​​表示该集合的大小,之后xx个互不相同的整数表示该集合的元素。
集合里的数字都是正整数且不大于300300.

1\leq1≤NN\leq30≤30,1\leq1≤L\leq5L≤5,1\leq1≤A_iA​i​​\leq10≤10,1 \leq L \leq N1≤L≤N

hack时建议输出最后一行的行末回车;每一行的结尾不要输出空格。

输出描述
对于每组数据输出一行YESYES或NONO

输入样例
2
2 1
1 1
1 2
3 2
3 1 2 3
3 4 5 6
3 2 5 6

输出样例
NO
YES

Hint
对于第二个样例,有三个集合{1 2 3},{4 5 6},{2 5 6} 你要划成两个部分。
有一种方案是把第二个和第三个集合划成一个部分,第一个在另一个部分。有一种方案是把第二个和第三个集合划成一个部分,第一个在另一个部分。 第二个和第三个集合的数字有一个交集{6},所以合法。
还有一种划分方案就是把第一个和第三个集合划成一个部分,第二个在另一个部分。


这道题就是暴力。

已ac的代码。

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 310
#define M 40
#define L 20

bool mark[M];
int numat
[M];
int hasnum[M][L];
int n;

int allmark(){
for(int i=0;i<n;i++){
if(mark[i]==false){
return i;
}
}

return -1;
}

bool find(int l){
int temp=allmark();

if(temp==-1){
return true;
}
else{
if(l==0){
return false;
}
else{
for(int j=1;j<=hasnum[temp][0];j++){
int hasmark
;
int tempnum=hasnum[temp][j];//不能定义为全局变量,因为在递归中,定义成全局变量后,会出错。

hasmark[0]=0;

for(int k=1;k<=numat[tempnum][0];k++){
if(mark[numat[tempnum][k]]==false){
mark[numat[tempnum][k]]=true;
hasmark[++hasmark[0]]=numat[tempnum][k];
}
}

if(find(l-1)){
return true;
}
else{
for(int k=1;k<=hasmark[0];k++){
mark[hasmark[k]]=false;
}
}

}

return false;
}
}
}

int main(){
int t;
int l;

scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&l);
memset(numat,0,sizeof(numat));
memset(mark,false,sizeof(mark));

for(int i=0;i<n;i++){
scanf("%d",&hasnum[i][0]);

for(int j=1;j<=hasnum[i][0];j++){
int temp;
scanf("%d",&temp);
hasnum[i][j]=temp;
numat[temp][++numat[temp][0]]=i;
}
}

if(find(l)){
printf("YES\n");
}
else{
printf("NO\n");
}
}

return 0;
}

 
感觉自己写的代码太复杂了,又从网上找了一份,学习一下思路,真的顺了很多。虽然思路简单的代码时间长了一点,但是让人写起来更省事。
已ac的代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 310
#define M 40
#define L 20

bool vis
;
int numat[M][L];
int n,l;

void init(){
memset(vis,false,sizeof(vis));
scanf("%d%d",&n,&l);

for(int i=0;i<n;i++){
scanf("%d",&numat[i][0]);

for(int j=1;j<=numat[i][0];j++){
scanf("%d",&numat[i][j]);
}
}

return;
}

bool has(int u){
for(int i=1;i<=numat[u][0];i++){
if(vis[numat[u][i]]){
return true;
}
}

return false;
}

bool dfs(int u,int d){
if(u>=n){//集合存在0到n-1,而不是1到n,所以是>=,而不是>
return true;
}
else if(d>l){
return false;
}
else{
if(has(u)){
return dfs(u+1,d);
}
else{
for(int i=1;i<=numat[u][0];i++){
vis[numat[u][i]]=true;
if(dfs(u+1,d+1)){
return true;
}
else{
vis[numat[u][i]]=false;
}
}

return false;
}
}
}

int main(){
int t;

scanf("%d",&t);
while(t--){
init();
printf("%s\n",dfs(0,0)?"YES":"NO");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: