找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1899|回复: 36

[研讨] 匈牙利算法相关问题

[复制链接]

已领礼包: 1883个

财富等级: 堆金积玉

发表于 2020-2-5 01:12:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 aimisiyou 于 2020-2-5 01:27 编辑

1、如何用列表表示效率矩阵?
2、效率矩阵每行减去每行最小值,如何实现?
3、已知效率矩阵中的一些0元素,如何用最少的直线覆盖所有的0?
4、如何实现未被直线覆盖的元素减去最小值,与未被覆盖元素不同行不同列元素加上最小值?
5,如何找出构成n阶独行独列的0元素?

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 08:29:30 | 显示全部楼层
定个小目标,实现以上五条。目前已实现了1,2。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 08:57:35 | 显示全部楼层
如果第3解决了,第4个也就很好解决了,第5其实就是对最后结果再使用一次3。所以关键是要解决3,这样也就可以用lisp计算指派问题。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 09:14:22 | 显示全部楼层
本帖最后由 aimisiyou 于 2020-2-5 09:47 编辑

对于第3条,我们可以每次删除行或列里0最多的那行或那列,作为画一条直线,再按此规则对余下的进行处理,应该就是用最少的直线覆盖所有的0了。经检查,这种处理不正确。正确的做法应该是先找0元素最多的那行或那列,如果一开始是某行0元素最多,接下来找该行0元素所在列中最多0元素的那列,再找该列上0元素最多的行(前面的0元素最多的那行除外)……,直至没有0元素;如果一开始是某列0元素最多,接下来找该列0元素所在行中最多0元素的那行,再找该行上0元素最多的列(前面0元素最多的列除外),……直至没有0元素。有时行或列0元素都是最多,就并行运算。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 5295个

财富等级: 富甲天下

发表于 2020-2-5 09:57:38 | 显示全部楼层
参考资料:https://www.cnblogs.com/shenben/p/5573788.html


基本概念—二分图

二分图:是图论中的一种特殊模型。若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为一个为二分图。



匹配:一个匹配即一个包含若干条边的集合,且其中任意两条边没有公共端点。如下图,图3的红边即为图2的一个匹配。





1 最大匹配
    在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,则称M是一个匹配。选择这样的边数最大的子集称为图的最大匹配问题,最大匹配的边数称为最大匹配数.如果一个匹配中,图中的每个顶点都和图中某条边相关联,则称此匹配为完全匹配,也称作完备匹配。如果在左右两边加上源汇点后,图G等价于一个网络流,最大匹配问题可以转为最大流的问题。解决此问的匈牙利算法的本质就是寻找最大流的增广路径。上图中的最大匹配如下图红边所示:



2 最优匹配

最优匹配又称为带权最大匹配,是指在带有权值边的二分图中,求一个匹配使得匹配边上的权值和最大。一般X和Y集合顶点个数相同,最优匹配也是一个完备匹配,即每个顶点都被匹配。如果个数不相等,可以通过补点加0边实现转化。一般使用KM算法解决该问题。



3 最小覆盖

二分图的最小覆盖分为最小顶点覆盖和最小路径覆盖:

①最小顶点覆盖是指最少的顶点数使得二分图G中的每条边都至少与其中一个点相关联,二分图的最小顶点覆盖数=二分图的最大匹配数;

②最小路径覆盖也称为最小边覆盖,是指用尽量少的不相交简单路径覆盖二分图中的所有顶点。二分图的最小路径覆盖数=|V|-二分图的最大匹配数;



4 最大独立集

    最大独立集是指寻找一个点集,使得其中任意两点在图中无对应边。对于一般图来说,最大独立集是一个NP完全问题,对于二分图来说最大独立集=|V|-二分图的最大匹配数。如下图中黑色点即为一个最大独立集:



基本概念—匈牙利算法

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边...形成的路径叫交替路。*

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)。



二、最大匹配与最小点覆盖

最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边

最小割定理是一个二分图中很重要的定理:一个二分图中的最大匹配数等于这个图中的最小点覆盖数。



最小点集覆盖==最大匹配。在这里解释一下原因,首先,最小点集覆盖一定>=最大匹配,因为假设最大匹配为n,那么我们就得到了n条互不相邻的边,光覆盖这些边就要用到n个点。现在我们来思考为什么最小点击覆盖一定<=最大匹配。任何一种n个点的最小点击覆盖,一定可以转化成一个n的最大匹配。因为最小点集覆盖中的每个点都能找到至少一条只有一个端点在点集中的边(如果找不到则说明该点所有的边的另外一个端点都被覆盖,所以该点则没必要被覆盖,和它在最小点集覆盖中相矛盾),只要每个端点都选择一个这样的边,就必然能转化为一个匹配数与点集覆盖的点数相等的匹配方案。所以最大匹配至少为最小点集覆盖数,即最小点击覆盖一定<=最大匹配。综上,二者相等。



三、匈牙利算法

由增广路的性质,增广路中的匹配边总是比未匹配边多一条,所以如果我们放弃一条增广路中的匹配边,选取未匹配边作为匹配边,则匹配的数量就会增加。匈牙利算法就是在不断寻找增广路,如果找不到增广路,就说明达到了最大匹配。

先给一个例子
1、起始没有匹配



2、选中第一个x点找第一跟连线





3、选中第二个点找第二跟连线





4、发现x3的第一条边x3y1已经被人占了,找出x3出发的的交错路径x3-y1-x1-y4,把交错路中已在匹配上的边x1y1从匹配中去掉,剩余的边x3y1 x1y4加到匹配中去





5、同理加入x4,x5。

匈牙利算法可以深度有限或者广度优先,刚才的示例是深度优先,即x3找y1,y1已经有匹配,则找交错路。若是广度优先,应为:x3找y1,y1有匹配,x3找y2。



算法模板(邻接表 & C++)



深度优先匈牙利算法代码:

复制代码
#define maxn 10//表示x集合和y集合中顶点的最大个数!
int nx,ny;//x集合和y集合中顶点的个数
int edge[maxn][maxn];//edge[j]为1表示ij可以匹配
int cx[maxn],cy[maxn];//用来记录x集合中匹配的y元素是哪个!
int visited[maxn];//用来记录该顶点是否被访问过!
int path(int u)
{
     int v;
     for(v=0;v<ny;v++)
     {
         if(edge[v]&&!visited[v])
         {
             visited[v]=1;
            if(cy[v]==-1||path(cy[v]))//如果y集合中的v元素没有匹配或者是v已经匹配,但是从cy[v]中能够找到一条增广路
             {
                 cx=v;
                 cy[v]=u;
                 return 1;
             }
         }
     }
     return 0;
}
int maxmatch()
{
     int res=0;
     memset(cx,0xff,sizeof(cx));//初始值为-1表示两个集合中都没有匹配的元素!
     memset(cy,0xff,sizeof(cy));
     for(int i=0;i<=nx;i++)
     {
         if(cx==-1)
         {
             memset(visited,0,sizeof(visitited));
             res+=path(i);
         }
     }
     return res;
}
复制代码
四、相关POJ题目

(1) poj3041

题目意思就是一颗子弹可以干掉任意一行或一列的障碍,问最少需要花费多少子弹清除呢

也就是求最小点集覆盖。

复制代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#define Max 505
using namespace std;
int a[Max][Max];
int visit[Max];
int match[Max];
int N,K;
int path(int u)
{
    int v;
    for(v=1;v<=N;v++)
    {
          if(a[v] && !visit[v])
          {
                visit[v] = 1;
                if(match[v] == -1 || path(match[v]))
                {
                            match[v] = u;
                            return 1;
                }  
          }
    }
    return 0;
}
int main()
{
                                                                                                         
      int i,j,k,count;
      scanf("%d %d",&N,&K);
                                                                                                         
      memset(a,0,sizeof(a));
      memset(match,-1,sizeof(match));
      count = 0;
      for(i=1;i<=K;i++)
      {
           scanf("%d %d",&j,&k);
           a[j][k] = 1;
      }
                                                                                                            
      for(i=1;i<=N;i++)
      {
             memset(visit,0,sizeof(visit));
             if(path(i))
               count++;
      }
      printf("%d\n",count);
                                                                                                         
      return 0;
}
复制代码
(2) poj3020

此题重要的是做出图来,以什么样的观点作图。可以画 h*w -> h*w 的图,点i与上下左右四个点有边存在,求最大匹配,最后结果为 总点数 - 最大匹配/2

复制代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#define Max 520
using namespace std;
int a[Max][Max];
int visit[Max];
int match[Max];
int N;
char str[50][15];
int path(int u)
{
    int v;
    for(v=1;v<=N;v++)
    {
          if(a[v] && !visit[v])
          {
                visit[v] = 1;
                if(match[v] == -1 || path(match[v]))
                {
                            match[v] = u;
                            return 1;
                }  
          }
    }
    return 0;
}
int Find()
{
    int count = 0;
    int i;
    for(i=1;i<=N;i++)
    {
             memset(visit,0,sizeof(visit));
             if(path(i))
               count++;
    }
    return count;
}
int init(int h,int w) {
    int ctr,i,j;
    int x,y;
    int s,d;
    ctr=0;
    for ( i=1;i<=h;i++ ) {
        for ( j=1;j<=w;j++ ) {
            if ( str[j]=='*' ) {
                ctr++;
                x=i;
                y=j;
                s=(x-1)*w+y;
                if ( y+1<=w&&str[x][y+1]=='*' ) {
                    d=(x-1)*w+y+1;
                    a[d]=1;
                }
                if ( x+1<=h&&str[x+1][y]=='*' ) {
                    d=(x)*w+y;
                    a[d]=1;
                }
                if ( y-1>=1&&str[x][y-1]=='*' ) {
                    d=(x-1)*w+y-1;
                    a[d]=1;
                }
                if ( x-1>=1&&str[x-1][y]=='*' ) {
                    d=(x-2)*w+y;
                    a[d]=1;
                }
            }
        }
    }
    return ctr;
}
int main()
{
                           
      int i,j,k,n,totalnum,matchnum,h,w;
      scanf("%d",&n);
      while(n--)
      {
          memset(a,0,sizeof(a));
          memset(match,-1,sizeof(match));
                                 
          scanf("%d %d",&h,&w);
          getchar();
          for(i=1;i<=h;i++)
          {
              for(j=1;j<=w;j++)
              {
                 scanf("%c",&str[j]);
              }
              getchar();
          }
                                 
          totalnum = init(h,w);
          N = h*w;
          matchnum = Find();
                                 
          printf("%d\n",totalnum - matchnum/2);
                                                
                                 
      }
      return 0;
}//二分图
复制代码
如果你还没有看明白,再看看这里:http://blog.csdn.net/dark_scope/article/details/8880547

pass:个人觉得写得不错,就贴上了

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 10:24:11 | 显示全部楼层
核心就是这个问题"一颗子弹可以干掉任意一行或一列的障碍,问最少需要花费多少子弹清除呢",当然最少的方式可能有很多,只要找到一个就行。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 10:43:03 | 显示全部楼层
如图 ,我们可以最少用4条直线覆盖所有的0。若用(i,0)表示第i行,(0,j)表示第j列,如何得到我们想要的结果((0,1)(0,2)(0,5)(5,0))?
hh.png
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 11:13:52 | 显示全部楼层
如图,已知最少要用5条直线才能覆盖所有的0,5条直线为((0,1)(0,3)(0,5)(4,0)(5,0)),如何得到三角形所在的坐标((0,0)(1,4)(2,2)(3,3)(4,1))?



-7ba297739a8f39a0.png
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 16:32:01 | 显示全部楼层
首先我们找出所有0元素分布的位置,如lst0=((1 1) (2 3) (2 5) (3 1) (3 3) (4 4) (4 5) (5 1) (5 2) (5 3) (5 4) (5 5))。
接下来我们统计每行每列的0元素的个数,即lst0_rc=((1 0 1)(2 0 2)(3 0 2)(4 0 2)(5 0 5)(0 1 3)(0 2 1)(0 3 3)(0 4 2)(0 5 3)),其中元素(i 0 num)代表第i行共有num个0,(0 j num)代表第j列共有num个0。
找出num最大的值所对应的,即为(5 0 5),表示0元素最多的是第5行(为5个),此时一条直线可以覆盖第5行。找出第5行中0元素的分布,lst0_max=((5 1) (5 2) (5 3) (5 4) (5 5)),同时将其从lst0中删除,即lst0=((1 1) (2 3) (2 5) (3 1) (3 3) (4 4) (4 5))。
再对lst0统计每行每列的0元素的个数,即更新lst0_rc=((1 0 1)(2 0 2)(3 0 2)(4 0 2)),0元素最多的为第2行、第3行、第4行,都是2个0,故可以用三条直线覆盖这3行的0,并将这三行删除,更新lst0=((1 1)),还需要一条直线覆盖(1 1)处的0元素,这样至少共计5条直线,5*5=25刚好等于列表lst中的元素个数,即此时一定存在解(每行每列只有一个1)。
那么再反推回去,第一0元素的位置选(1 1),删除第1行或第1列的0元素的位置,即lst0=((2 3) (2 5) (3 3) (4 4) (4 5) (5 2) (5 3) (5 4) (5 5))。lst0_rc=((2 0 2)(3 0 1)(4 0 2)(5 0 3)(0 2 1)(0 3 3)(0 4 1)(0 5 3)),删除第5行和第5列(最多3个0),lst0=((2 3)   (3 3) (4 4)),lst0_rc=((2 0 1)(3 0 1)(4 0 1)(0 3 2)(0 4 1)),删除第3列,lst0=((4,4)),故第2个0元素位置选(4,4)……
最后选出的5个0元素的位置((1 1)(4 4)(2 5)(3 3)(5 2)).
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-5 16:36:11 | 显示全部楼层
好像一次划掉多行会出问题,还是得一步步来。规定由行到列,由小到大每一步用一条直线划掉最多0元素的那行或那列,剩下的重复此过程。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 960个

财富等级: 财运亨通

发表于 2020-2-6 12:53:02 | 显示全部楼层
没看太明白,学习一下
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-6 14:18:19 | 显示全部楼层
本帖最后由 aimisiyou 于 2020-2-6 14:22 编辑

完美解决了最大匹配问题,剩下的就是不断增加新的0元素,找到新的最大匹配,直到完全匹配。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-6 18:48:07 | 显示全部楼层
_$ (setq x 4 y 6 pdlst '((1 2)(1 4)(2 1)(2 5)(3 2)(4 1)(4 3)(4 5)(4 6)));;;X中有4个节点,Y中有6个节点 ,如果X中的1和Y中的2有关联,则将'(1 2)置入pdlst中
(setq n (max x y))   
(defun fnlst (nn)
  (setq i nn n_lst nil)
  (while (> i 0)
      (setq i (- i 1))
      (setq n_lst (cons i n_lst))
   )
)
(setq lst (fnlst (* n n)))                                        ;;;用列表存储关系矩阵,初始化lst   
(defun rc_num (pt)
   (+ (* n (- (car pt) 1)) (cadr pt) -1)
)                                                                  ;;;将坐标(i  j)转化为lst中的对应序号
(setq zero_lst (mapcar 'rc_num pdlst))
(setq lst (mapcar '(lambda (x) (if (member x zero_lst) 0 1)) lst))
(defun splst (llst)
  (setq lst1 (vl-sort llst '<) n_sum (length llst))
  (mapcar '(lambda (x) (list x (- n_sum (length (vl-remove x llst))))) lst1)
)
(defun hx_rcmax (rclst_zero)
  (cdr (car (vl-sort
        (append (mapcar '(lambda (x) (list (cadr x) (car x) 0 )) (splst (mapcar 'car rclst_zero)))
             (mapcar '(lambda (x) (list (cadr x) 0 (car x) )) (splst (mapcar 'cadr rclst_zero)))
      )
        '(lambda (ea eb)
          (> (car ea) (car eb))
       )
  )
   )
  )
)
(defun hx_num (rclst_zero)
  (cond
       ((= (length rclst_zero) 1) (setq linelst rclst_zero))
       ((and (> (length rclst_zero) 1) (null (vl-remove 0 (mapcar '(lambda (x) (- (cadr x) (cadr (car rclst_zero)))) rclst_zero))))
      (setq linelst (list (list 0 (cadr (car rclst_zero)))))
    )
       ((and (> (length rclst_zero) 1) (null (vl-remove 0 (mapcar '(lambda (x) (- (car x) (car (car rclst_zero)))) rclst_zero))))
      (setq linelst (list (list (car (car rclst_zero)) 0)))
    )
       (t (progn
          (setq hx (hx_rcmax rclst_zero))
    (if (> (car hx) (cadr hx))
        (setq linelst (cons hx (hx_num (vl-remove nil (mapcar '(lambda (x) (if (= (car hx) (car x)) nil x)) rclst_zero)))))
        (setq linelst (cons hx (hx_num (vl-remove nil (mapcar '(lambda (x) (if (= (cadr hx) (cadr x)) nil x)) rclst_zero)))))
    )
   )  
    )
   )
)
(defun sxlst (hhxlst rrclst0)
   (setq ptlst nil ij (length hhxlst))
   (repeat ij
      (if (> (apply '+ (mapcar '(lambda (x) (* (car x )(cadr x))) hhxlst)) 0)
        (progn
       (setq pt (car (vl-remove nil (mapcar '(lambda (x) (if (> (* (car x )(cadr x)) 0) x nil)) hhxlst))))
             (setq ptlst (cons pt ptlst))
             (setq rrclst0 (vl-remove nil (mapcar '(lambda (x) (if (or (= (car x) (car pt)) (= (cadr x) (cadr pt))) nil x)) rrclst0)))
    (if rrclst0
      (setq hhxlst (hx_num rrclst0))
     )
            )
           (progn
       (if (> (car (car hhxlst)) 0)
        (setq pt (car (vl-sort (vl-remove nil(mapcar '(lambda (x) (if (= (car x) (car (car hhxlst))) x nil)) rrclst0)) '(lambda (ea eb) (< (cadr ea) (cadr eb))))))
        (setq pt (car (vl-sort (vl-remove nil(mapcar '(lambda (x) (if (= (cadr x) (cadr (car hhxlst))) x nil)) rrclst0)) '(lambda (ea eb) (< (car ea) (car eb))))))                 
    )
             (setq ptlst (cons pt ptlst))
             (setq rrclst0 (vl-remove nil (mapcar '(lambda (x) (if (or (= (car x) (car pt)) (= (cadr x) (cadr pt))) nil x)) rrclst0)))
    (if rrclst0
        (setq hhxlst (hx_num rrclst0))
     )
            )  
      )
   )
   ptlst
)
(sxlst (hx_num pdlst) pdlst)
((1 2) (1 4) (2 1) (2 5) (3 2) (4 1) (4 3) (4 5) (4 6))
6
FNLST
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35)
RC_NUM
(1 3 6 10 13 18 20 22 23)
(1 0 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1)
SPLST
HX_RCMAX
HX_NUM
SXLST
((2 5) (4 1) (1 4) (3 2))
_$
-141eb8198d7ec094.png
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-6 20:48:44 | 显示全部楼层
_$ (setq x 6 y 7 pdlst '((1 1)(1 2)(1 4)(2 2)(2 5)(3 1)(3 4)(3 7)(4 3)(4 4)(4 6)(5 4)(6 4)));;;X中有4个节点,Y中有6个节点 ,如果X中的1和Y中的2有关联,则将'(1 2)置入pdlst中
(setq n (max x y))   
(defun fnlst (nn)
  (setq i nn n_lst nil)
  (while (> i 0)
      (setq i (- i 1))
      (setq n_lst (cons i n_lst))
   )
)
(setq lst (fnlst (* n n)))                                        ;;;用列表存储关系矩阵,初始化lst   
(defun rc_num (pt)
   (+ (* n (- (car pt) 1)) (cadr pt) -1)
)                                                                  ;;;将坐标(i  j)转化为lst中的对应序号
(setq zero_lst (mapcar 'rc_num pdlst))
(setq lst (mapcar '(lambda (x) (if (member x zero_lst) 0 1)) lst))
(defun splst (llst)
  (setq lst1 (vl-sort llst '<) n_sum (length llst))
  (mapcar '(lambda (x) (list x (- n_sum (length (vl-remove x llst))))) lst1)
)
(defun hx_rcmax (rclst_zero)
  (cdr (car (vl-sort
        (append (mapcar '(lambda (x) (list (cadr x) (car x) 0 )) (splst (mapcar 'car rclst_zero)))
             (mapcar '(lambda (x) (list (cadr x) 0 (car x) )) (splst (mapcar 'cadr rclst_zero)))
             )
        '(lambda (ea eb)
                 (> (car ea) (car eb))
              )
                )
   )
  )
)
(defun hx_num (rclst_zero)
  (cond
       ((= (length rclst_zero) 1) (setq linelst rclst_zero))
       ((and (> (length rclst_zero) 1) (null (vl-remove 0 (mapcar '(lambda (x) (- (cadr x) (cadr (car rclst_zero)))) rclst_zero))))
             (setq linelst (list (list 0 (cadr (car rclst_zero)))))
           )
       ((and (> (length rclst_zero) 1) (null (vl-remove 0 (mapcar '(lambda (x) (- (car x) (car (car rclst_zero)))) rclst_zero))))
             (setq linelst (list (list (car (car rclst_zero)) 0)))
           )
       (t (progn
                 (setq hx (hx_rcmax rclst_zero))
                         (if (> (car hx) (cadr hx))
                             (setq linelst (cons hx (hx_num (vl-remove nil (mapcar '(lambda (x) (if (= (car hx) (car x)) nil x)) rclst_zero)))))
                             (setq linelst (cons hx (hx_num (vl-remove nil (mapcar '(lambda (x) (if (= (cadr hx) (cadr x)) nil x)) rclst_zero)))))
                         )
                        )  
           )
   )
)
(defun sxlst (hhxlst rrclst0)
   (setq ptlst nil ij (length hhxlst))
   (repeat ij
      (if (> (apply '+ (mapcar '(lambda (x) (* (car x )(cadr x))) hhxlst)) 0)
               (progn
                     (setq pt (car (vl-remove nil (mapcar '(lambda (x) (if (> (* (car x )(cadr x)) 0) x nil)) hhxlst))))
             (setq ptlst (cons pt ptlst))
             (setq rrclst0 (vl-remove nil (mapcar '(lambda (x) (if (or (= (car x) (car pt)) (= (cadr x) (cadr pt))) nil x)) rrclst0)))
                         (if rrclst0
                           (setq hhxlst (hx_num rrclst0))
                          )
            )
                  (progn
                     (if (> (car (car hhxlst)) 0)
                             (setq pt (car (vl-sort (vl-remove nil(mapcar '(lambda (x) (if (= (car x) (car (car hhxlst))) x nil)) rrclst0)) '(lambda (ea eb) (< (cadr ea) (cadr eb))))))
                             (setq pt (car (vl-sort (vl-remove nil(mapcar '(lambda (x) (if (= (cadr x) (cadr (car hhxlst))) x nil)) rrclst0)) '(lambda (ea eb) (< (car ea) (car eb))))))                 
                         )
             (setq ptlst (cons pt ptlst))
             (setq rrclst0 (vl-remove nil (mapcar '(lambda (x) (if (or (= (car x) (car pt)) (= (cadr x) (cadr pt))) nil x)) rrclst0)))
                         (if rrclst0
                             (setq hhxlst (hx_num rrclst0))
                          )
            )  
      )
   )
   ptlst
)
(sxlst (hx_num pdlst) pdlst)
((1 1) (1 2) (1 4) (2 2) (2 5) (3 1) (3 4) (3 7) (4 3) (4 4) (4 6) (5 4) (6 4))
7
FNLST
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48)
RC_NUM
(0 1 3 8 11 14 17 20 23 24 26 31 38)
(0 0 1 0 1 1 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1)
SPLST
HX_RCMAX
HX_NUM
SXLST
(nil (4 3) (3 1) (2 2) (1 4))
_$

Screenshot_20200206_195543_com.android.browser.jpg
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 1883个

财富等级: 堆金积玉

 楼主| 发表于 2020-2-6 20:51:15 | 显示全部楼层
本帖最后由 aimisiyou 于 2020-2-6 20:54 编辑

找了网上数据测试了下,结果有误且出现了个nil,得找找原因。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-12-22 09:55 , Processed in 0.526948 second(s), 65 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表