hdu5506

GT and set

 
 Accepts: 35
 
 Submissions: 194
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
NN个集合,每个集合中有A_iAi个数。
你要将这NN个集合划成LL个部分,使得每个部分的集合至少有一个共有的数。
如果至少有一个解输出YESYES,否则输出NONO
输入描述
第一行一个数T表示数据组数。(TT\leq2020)

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

1\leq1NN\leq30301\leq1L\leq5L51\leq1A_iAi\leq10101 \leq L \leq N1LN

hack时建议输出最后一行的行末回车;每一行的结尾不要输出空格。
输出描述
对于每组数据输出一行YESYESNONO
输入样例
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[N][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[N];
                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[N];
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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
协同过滤算法(Collaborative Filtering)是一种经典的推荐算法,其基本原理是“协同大家的反馈、评价和意见,一起对海量的信息进行过滤,从中筛选出用户可能感兴趣的信息”。它主要依赖于用户和物品之间的行为关系进行推荐。 协同过滤算法主要分为两类: 基于物品的协同过滤算法:给用户推荐与他之前喜欢的物品相似的物品。 基于用户的协同过滤算法:给用户推荐与他兴趣相似的用户喜欢的物品。 协同过滤算法的优点包括: 无需事先对商品或用户进行分类或标注,适用于各种类型的数据。 算法简单易懂,容易实现和部署。 推荐结果准确性较高,能够为用户提供个性化的推荐服务。 然而,协同过滤算法也存在一些缺点: 对数据量和数据质量要求较高,需要大量的历史数据和较高的数据质量。 容易受到“冷启动”问题的影响,即对新用户或新商品的推荐效果较差。 存在“同质化”问题,即推荐结果容易出现重复或相似的情况。 协同过滤算法在多个场景中有广泛的应用,如电商推荐系统、社交网络推荐和视频推荐系统等。在这些场景中,协同过滤算法可以根据用户的历史行为数据,推荐与用户兴趣相似的商品、用户或内容,从而提高用户的购买转化率、活跃度和社交体验。 未来,协同过滤算法的发展方向可能是结合其他推荐算法形成混合推荐系统,以充分发挥各算法的优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值