1、我们采用了并查集的方法,首先,我们考虑了这样一个问题:在第n天的时候,计算机病毒只可以感染防御等级小于等于n的计算机,所以,在对计算机进行感染或者分类时,只需要考虑防御等级小于等于n的计算机,其他的计算机忽略不考虑。 每一天开始,我们需要对计算机网络进行一次分组操作,将低于某一等级的区域归为一个集合,并为集合设立虚拟根节点,集合中所有的结点的父母亲指针都指向虚拟根结点,在划分集合时,如之前所说的,不考虑小于等于天数的防御等级的计算机。 分组操作首先由一个循环开始,从二维矩阵的第一个数开始,m*n依次查找,如果满足要求(非病毒,防御等级=high_level;day-) /第day天,使用负数,
2、便于与防御等级比较 cout第-day天endl; for(i=0;im+2;i+) for(j=0;jn+2;j+) netij.visit=0; /每天开始标识位置零 for(i=1;m+1; for(j=1;n+1; if(netij.type_level=day & netij.visit=0) /当满足该结点(非病毒、防御等级不大于天数、未被访问) root_x=i; /记录虚拟根节点坐标 root_y=j; p=&netij; /保存根结点 group(i,j); /执行分组 while(p!=NULL) couttype_levelx,ychild; /每天的分组完成后输出当天分
3、组情况 cout cout computer *index; for(int k=0;kcount;k+) /按病毒的型号顺序进行感染,每个病毒以其单链表次序依次感染 coutvirus_typekparent; /保存病毒根结点 while(index! infect(index-x,index-y,k); /从根结点按单链表顺序依次感染,直到空 cout)被感染 index=index- 源码:#includefstreamusing namespace std;struct computer int type_level; int visit; int x,y; computer *ch
4、ild; computer *parent;class XMSXprivate: int m,n;/记录计算机网络大小 int root_x,root_y;/临时变量,用于记录虚拟根节点的位置 int day;/当前天数 int count;/病毒数 int num;/待查询的病毒数 int high_level;/最高的防御等级 int virus_type100;/病毒种类 int virus_search100;/待查找的病毒种类 computer net100100;/计算机网络 computer *list_end100;/单链表表尾 computer *p;/临时变量public:
5、 void enter();/输入函数 void print();/将计算机网络输出在屏幕中 void infect(int a,int b,int k); /感染函数,对位置在(a,b)的结点进行递归感染,感染类型为virus_typek void group(int a,int b); /集合划分函数,对位置在(a,b)的结点递归查找满足条件的结点 void union_find(); /并查集,分组并感染 void count_type(); /统计不同种病毒的数目并输出/=输入函数=enter() int i,j,k; /定义三个整型变量用于循环 count=0;/输入前,病毒数为0
6、high_level=0;/输入前,最高防御等级为0 ifstream infile; infile.open(input.txt);/文件夹输入 infilemn;/输入行数和列数 for(i=0; /m+2即增加了墙 for(j=0;j+) /n+2即增加了墙 netij.type_level=0; /先令所有的计算机防御等级为0 netij.child=NULL; /所有的计算机孩子指针指向空 netij.parent=& /所有的计算机父母指针指向自己 netij.x=i; /在x,y中记录自己在矩阵中的位置 netij.y=j; for(i=1; for(j=1; infilenet
7、ij.type_level; /文件夹输入计算机的防御等级或病毒型号 if(netij.type_level0) /当防御等级大于0时,即为病毒型号 virus_typecount=netij.type_level; /记录病毒型号序列 list_endcount=& /此时将第count号病毒单链表的尾指针指向该病毒 /即将病毒作为自己单链表的头结点 count+; /count加1,当扫描完所有病毒以后,count即为病毒总数 else if(netij.type_levelvirus_searchk;/输入需要查找的病毒型号 /=输出矩阵=print() for(int i=1; for
8、(int j=1;netij.type_level /=分组函数=group(int a,int b)/给分组函数一个坐标(a,b),即可为这个坐标所在区域分组 netab.visit=1; /表示这个坐标已经被访问过 if(neta-1b.type_level neta-1b.visit=0) /当这个坐标的上方结点满足(非病毒、防御等级不大于天数、未被访问)时 neta-1b.parent=&netroot_xroot_y; /将上方结点的父母指针指向虚拟根节点 p-child=&neta-1b; /区域单链表表尾的孩子指针指向该结点 p=p- /将表尾向后推移 group(a-1,b);
9、 /递归对上方结点求分组 if(netab+1.type_level netab+1.visit=0) /当这个坐标的右方结点满足(非病毒、防御等级不大于天数、未被访问)时 netab+1.parent=&netab+1; group(a,b+1); if(neta+1b.type_level neta+1b.visit=0) /当这个坐标的下方结点满足(非病毒、防御等级不大于天数、未被访问)时 neta+1b.parent=&neta+1b; group(a+1,b); if(netab-1.type_level netab-1.visit=0) /当这个坐标的左方结点满足(非病毒、防御等级
10、不大于天数、未被访问)时 netab-1.parent=&netab-1; group(a,b-1);/=感染函数=infect(int a,int b,int k)/给出一个坐标以及病毒型号,即以该病毒感染此结点所在区域=day) /当非病毒,防御等级不大于天数时 p=neta-1b.parent; /保存该结点所在区域的虚拟根节点 list_endk-child=p; /将k号病毒链表尾部孩子指针指向虚拟根节点type_level=list_endk-type_level; /该区域所有结点的防御等级改为病毒型号parent=list_endk- /取消虚拟根节点, while(p-child! /以原始病毒为根结点 p=p- p- list_endk=p; /表尾推移到单链表最尾端 p=netab+1.parent; p=neta+1b.parent; p=netab-1.parent;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1