• [置顶] hdu1150解题报告--也可以说小白理解最小点覆盖学习总结


    在这个题目上理解了学长说的一句话:算法不难,题目难委屈.....找了很多结题报告,但是对于都没接触过“最小点覆盖”的我来说很是不解....于是请教了学长,现在以最通俗的方式描述,希望自己以后来看能一目了然,也能对刚接触最小点覆盖的人有帮助大笑(ps:文字看起来多,但是很通俗,后面又结合图加以详细描述)

    开始是自己理解,以为A机器有n个可以工作的地方,B有m个可以工作的地方,--完全错误..后面又不知道为什么别人的解题报告上匹配的数组为什么是map[101][101].自己就一直用map[202][1002]去做.不知道有多少人第一次看到题目能自己完全懂.哎哎只能怪自己太菜,而且还涉及到一个“最小点覆盖”的深奥东东大笑

    那么一如既往,还是个人觉得学习某一个知识点之前先粗俗的了解其是个什么东东,然后再去了解概念比较好...那么下面结合题目来了解:

    首先最最重要的是理解题意,有k个任务,每个任务task_i可以用机器A的x_i模式做,也可以由机器B的y_i模式做(值得注意的是只有两个机器,但是有不同的模式,每次可以在一个模式下工作),在做所有的任务之前,A与B的模式都最开始调为0,为了把所有任务做完,我们需要按照不同的任务,调制机器A或者B的模式,那么,我们最少要调制机器多少次,能完成所有的任务?
    比如
    任务task_0要么由A的模式0完成,要么由B的模式1完成,
    任务task_1要么由A的模式1完成,要么由B的模式0完成,
    那么我们要调整机器多少次呢?
    首先机器的模式都是0(再次说明题目中最开始的模式是0),用A的0先完成task_0,用B的0完成task_1就可以啦...所以,我们一次都不用调制
    但是如果还有几个个任务
    task_2要用A的1模式,或者B的2模式,
    task_3要么由A的2模式要么B的2模式完成    ..你要调制机器几次呢?
    可以有以下几个方案:
    1.调制A从0到1,完成task_2,然后调制A从1到2,完成task_3---总共调制2次
    2.调制A从0到1,完成task_2,然后调制B从0到2,完成task_3---总共调制也是2次
    3.调制B从0到2,那么就可以同时完成task2,task_3,-----------总共调制1次

    到这里,题目都差不多描述完啦,那么下面就是粗俗了解”最小点覆盖“这个新东西,并且如何将其和题目结合

    1.首先画图来理解“最小点覆盖”,就拿我们上面的例子来说,(先不管最小点覆盖这个概念)最开始把task和机器联系起来(就是task_i能给哪个机器的哪个模式做就连一条线),联系起来之后便是如下:

    从图中看,结合最开始的题意理解,可以知道task0和1都让A的0模式做,task2,3都让B的模式2去做可以达到题目要求:最少调整机器的次数,现在我们就把要做的工作当做联系A、B机器的线(从图中看得出每一个任务把机器的模式连接起来),简化为下图:

    那么现在我们A的0模式邻接了2条边,B的2模式邻接了2条边,我们知道边就是任务,图中的圆圈就是机器的模式,那么现在就题目就成了我们选最少的点(机器模式),可以邻接更多的线(任务),那么我们把邻接叫做覆盖,也就是说成了选最少的点,去覆盖尽可能多的边.....嘿嘿,是不是觉得"最小点覆盖"有那么点概念了呢?

    那么根据公式 :最小点覆盖=最大匹配 如果想知道为啥,推荐一个:最小点覆盖证明

    那么就直接上代码啦:附上详细解说(匈牙利模板。但是有个地方要注意)

    // 268k 0ms
    #include<stdio.h>
    #include<string.h>
    
    #define MAX 101
    
    int n,m,k;
    int map[MAX][MAX];//转化为求两个机器的模式匹配...那么数组大小就是这么大啦
    int link[MAX];
    bool useif[MAX];
    //模板就不附加说明啦
    bool dfs(int t)
    {
    	for(int i=0;i<m;i++)
    	{
    		if(!useif[i] && map[t][i])
    		{
    			useif[i]=true;
    			if(link[i]==-1 || can(link[i]))
    			{
    				link[i]=t;return true;
    			}
    		}
    	}
    	return false;
    }
    
    int match()
    {
    	int sum=0;
    	memset(link,-1,sizeof(link));
    	for(int i=0;i<n;i++)
    	{
    		memset(useif,false,sizeof(useif));
    		if(dfs(i))
    			sum++;
    	}
    	return sum;
    }
    
    int main()
    {
    	int a,b,t;
    	while(scanf("%d",&n),n)
    	{
    		scanf("%d%d",&m,&k);
    
    		memset(map,0,sizeof(map));
    		for(int i=0;i<k;i++)
    		{
    			scanf("%d%d%d",&t,&a,&b);
    			if(a>0 && b>0)//注意题目说开始的时候在modle0开始工作.那么要是有一个任务可以由A。B的模式0完成,完全不用考虑
    			  map[a][b]=1;
    		}
    		printf("%d
    ",match());
    	}
    	return 0;
    }

    个人愚昧的观点,,,欢迎大家讨论 大笑

  • 相关阅读:
    azkaban使用--指定executor
    azkaban使用--依赖dependencies作业
    azkaban用户管理及权限配置
    azkaban架构介绍
    azkaban工作流调度器及相关工具对比
    azkaban的简单使用
    Azkaban安装及分布式部署(multiple-executor)
    配置yum源
    idea搭建Eureka注册中心及配置密码登陆
    kudu导入文件(基于impala)
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3279834.html
Copyright © 2020-2023  润新知