人群(人堆)问题,算法求解

kingmax54212008 2017-04-04 11:17:27
题目:
人群(人堆)问题计算
如果 人0认识人1, 人1认识人2,那么可认为人0认识人2。 一个人群的概念为人之间相互认识或间接认识。
用n X n 方阵表示人与人,是否认识。 如: people[i][j]=0 表示 人i与人j,不认识。

约束: 1<=n <=300; 0<=i<=n; people[i][i]=1( 当0<=i<=n); people[i][j] =people[j][i] ( 当0<=i<=j<=n)

输入:人数n,后再输入方阵数组。


举例如下:
输入样例0:
4
1100
1110
0110
0001

输出:
2

输出答案解释说明,参考图示:


输入样例1:

5
10000
01000
00100
00010
00001
输出:
5

输出答案解释说明,参考图示:

...全文
312 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingmax54212008 2017-04-07
  • 打赏
  • 举报
回复
用无向图 连通性 算法 也可以。 http://blog.csdn.net/kingmax54212008/article/details/69229320 --------------------------------------- package ctong; import java.util.Arrays; import java.util.Random; public class Graph_DFS { /** * Ctong * @param args */ //建立一个标识数组,0表示未被发现的节点,1表示已被发现的节点,2表示邻接表检索完后的节点 private static int[] color; //记录连通图的个数 private static int count = 0; //遍历方法 public void DFS_visit(int[][] array,int n){ //节点n已查找 color[n]=1; System.out.println(Arrays.toString(color)); //从n出发查找与n相连的节点 for(int i = n;i<array.length;i++){ for(int j = 0;j<array.length;j++){ if(array[n][j]==1){ if(color[j]==0){ DFS_visit(array,j); } } } } color[n]=2; System.out.println(Arrays.toString(color)); //以上两次打印color数组是为了显示遍历过程,当某一次打印的数组只有2或0时,表示这里有一个已经查找完毕的连通图 } public Graph_DFS(int[][] graph){ //初始化color数组,表示该无向图的所有节点都没有查找过 for(int i = 0;i<graph.length;i++){ color[i]=0; } //图的遍历 for(int j = 0;j<graph.length;j++){ if(color[j]==0){ //每次执行以下2行代码,表示多出一个连通图 count++; DFS_visit(graph,j); } } } /** * 主函数 */ public static void main(String[] args) { //创建一个1,2,3和4,5,6的环 int[][] map1 = new int[][]{ {0,1,0}, {1,0,0}, {0,0,0}, }; int[][] map = new int[][]{ {0,1,0,0,0,0}, {1,0,0,0,0,0}, {0,0,0,1,0,0}, {0,0,1,0,0,0}, {0,0,0,0,0,1}, {0,0,0,0,1,0}}; //创建随机数组 int[][] map2 = createRandomBArray(); //打印 print(map2); System.out.println("随机创建的2维数组中,行号和列号表示2个节点,它们对应的数据表示它们的连接情况,0表示这两个节点未连通,1表示这两个节点连通"); //0表示未被发现的节点,1表示已被发现的节点,2表示邻接表检索完后的节点 color = new int[map2.length]; System.out.println("无向图的深度优先搜索:"); new Graph_DFS(map2); System.out.println("连通图个数为:"+count); } //创建一个随机的2维数组 private static int[][] createRandomBArray() { Random ra= new Random(); int n = ra.nextInt(5)+4; int[][] Barray= new int[n][n]; for(int k = 0;k<n;k++){ Barray[k][k]=0; } for(int i = 0 ;i<n;i++){ for(int j = 0 ;j<n;j++){ if(i!=j){ if(j>i){ if(Math.random()<0.5) Barray[i][j]= 1; else Barray[i][j]= 0; }else Barray[i][j]=Barray[j][i]; } } } return Barray; } //打印二维数组 public static void print(int[][] c){ for(int i=0;i<c.length;i++ ){ for(int j=0;j<c.length;j++ ){ if(c[i][j]==0) System.out.print(c[i][j]+"\t"); else System.out.print(c[i][j]+"\t"); } System.out.println(); } } }
kingmax54212008 2017-04-07
  • 打赏
  • 举报
回复
@bbjiabcd
bbjiabcd 2017-04-06
  • 打赏
  • 举报
回复

        private void btnCalc_Click(object sender, EventArgs e)
        {
            //将字符串数据读取到数组fzArr中
            string[] strfzArr = txtArr.Text.Split('\n');
            List<string> strfzList = new List<string>();
            string strlinetrim;
            //总人数
            int peopleCnt;
            string[] strlineArr;
            foreach (string strline in strfzArr)
            {
                strlinetrim = strline.Trim();
                if (strlinetrim.Length > 0)
                {
                    strfzList.Add(strlinetrim);
                }
            }
            peopleCnt = strfzList.Count;
            //方针数组
            bool[,] fzArr = new bool[peopleCnt, peopleCnt];
            //每个人属于群的序号(从1开始)
            int[] rqIndex = new int[peopleCnt];
            //每个序号是否被使用
            bool[] indexUseflag = new bool[peopleCnt + 1];
            //人群数
            int rqCnt = 0;

            //支持两种格式的输入
            //输入方式1:数字间没有空格
            if (strfzList[0].Length == peopleCnt)
            {
                for (int i = 0; i < peopleCnt; i++)
                {
                    for (int j = 0; j < strfzList[i].Length && j < peopleCnt; j++)
                    {
                        fzArr[i, j] = strfzList[i][j] != 48; //字符'0'的Ascii码为48
                    }
                }
            }
            //输入方式2:数字间有空格
            else
            {
                for (int i = 0; i < peopleCnt; i++)
                {
                    strlineArr = strfzList[i].Split(' ');
                    for (int j = 0; j < strlineArr.Length && j < peopleCnt; j++)
                    {
                        fzArr[i, j] = Convert.ToInt32(strlineArr[j]) != 0;
                    }
                }
            }

            //开始计算

            //群的序号(从1开始)
            int lei = 0;
            int temp;
            for (int i = 0; i < peopleCnt; i++)
            {
                for (int j = i + 1; j < peopleCnt; j++)
                {
                    if (fzArr[i, j])
                    {
                        if (rqIndex[i] == 0 && rqIndex[j] == 0)
                        {
                            rqIndex[j] = rqIndex[i] = ++lei;
                        }
                        else if (rqIndex[i] == 0)
                        {
                            rqIndex[i] = rqIndex[j];
                        }
                        else if (rqIndex[j] == 0)
                        {
                            rqIndex[j] = rqIndex[i];
                        }
                        else
                        {
                            if (rqIndex[i] > rqIndex[j])
                            {
                                temp = rqIndex[i];
                                for (int k = 0; k < rqIndex.Length; k++)
                                {
                                    if (rqIndex[k] == temp)
                                        rqIndex[k] = rqIndex[j];
                                }
                            }
                            else if (rqIndex[j] > rqIndex[i])
                            {
                                temp = rqIndex[j];
                                for (int k = 0; k < rqIndex.Length; k++)
                                {
                                    if (rqIndex[k] == temp)
                                        rqIndex[k] = rqIndex[i];
                                }
                            }
                        }
                    }
                    else
                    {
                        if (rqIndex[i] == 0)
                            rqIndex[i] = ++lei;
                        if (rqIndex[j] == 0)
                            rqIndex[j] = ++lei;
                    }
                }
            }

            foreach (int rqIndex1 in rqIndex)
            {
                if (!indexUseflag[rqIndex1])
                {
                    indexUseflag[rqIndex1] = true;
                    rqCnt++;
                }
            }
            MessageBox.Show(rqCnt.ToString());
        }
个人习惯:不喜欢用控制台做,喜欢用Winform做 本程序中不需要手动输入人数,程序会通过矩阵大小判断人数 运行结果:
kingmax54212008 2017-04-05
  • 打赏
  • 举报
回复
有源码么? 算法基础不是太好。 求赐教
angel6709 2017-04-05
  • 打赏
  • 举报
回复
典型的连通问题
stherix 2017-04-05
  • 打赏
  • 举报
回复
这个其实就是无向图的连通性和连通分支问题啊 比较容易的方法是对每一个点进行广度(深度)优先遍历,把每一次遍历到的点设标志已访问(移除遍历集合) 最终进行了多少次遍历就是有几个块
xuzuning 2017-04-05
  • 打赏
  • 举报
回复
你被你自己画的图给唬住了 其实换种方法表示 z0,z1 z1,z2 z2.z3 z4 就简单多了! 将每行视为一个集合 只是求交集、并集而已(C#都有提供)

110,561

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧