数据结构_队列应用举例_划分子集问题

经过一天的奋斗,解决~~~     ^_^   
      

 

队列应用举例--划分子集问题 - luojilie - luojilie的博客

 

     

Description

       已知集合A={a1,a2,……an},及集合上的关系R={ (ai,aj) | ai,aj?A, i?j},其中(ai,aj)表示ai与aj间存在冲突关系。要求将A划分成互不相交的子集A1,A2,……Ak,(k?n),使任何子集中的元素均无冲突关系,同时要求分子集个数尽可能少   

Sample Input

             A={1,2,3,4,5,6,7,8,9}

      R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9),(5,6), (5,4), (7,5), (7,6), (3,7), (6,3) }

Sample Output     

      A1={ 1,3,4,8 }

      A2={ 2,7 }

      A3={ 5 }

             A4={ 6,9 }

  (可行的子集划分)

Hint

算法思想:

利用循环筛选。从第一个元素开始,凡与第一个元素无冲突的元素划归一组;再将剩下的元素重新找出互不冲突的划归第二组;直到所有元素进组
所用数据结构
冲突关系矩阵
r[i][j]=1,  i,j有冲突
r[i][j]=0,  i,j无冲突
循环队列cq[n]
数组result[n]存放每个元素分组号
工作数组newr[n]

工作过程:
初始状态:A中元素放于cq中,result和newr数组清零,组号group=1
第一个元素出队,将r矩阵中第一行“1”拷入newr中对应位置,这样,凡与第一个元素有冲突的元素在newr中对应位置处均为“1”,下一个元素出队
若其在newr中对应位置为“1”,有冲突,重新插入cq队尾,参加下一次分组
若其在newr中对应位置为“0”, 无冲突,可划归本组;再将r矩阵中该元素对应行中的“1”拷入newr中
如此反复,直到9个元素依次出队,由newr中为“0”的单元对应的元素构成第1组,将组号group值“1”写入result对应单元中
令group=2,newr清零,对cq中元素重复上述操作,直到cq中front==rear,即队空,运算结束

 

队列应用举例--划分子集问题 - luojilie - luojilie的博客
 
 
 
 
Code:

     

// Author: essence_of_ACMER 
// Time:2011.8.6
// Theme:Array_Subset

 #include 
< iostream >
using   namespace  std;
#define  N 9
int  front = 0 ,rear = 0 ,group = 0 ;

void  division( int  r[][N], int  n, int  cq[ ], int  newer[ ], int  result[ ])   // 主要函数
{
    
int  k,pre,i;
    
for (k = 0 ;k < n;k ++ )
       {cq[k]
= k + 1 ;newer[k] = 0 ;}
    front
= n - 1 ;
    rear
= n - 1 ;
    group
= 1 ;
    pre
= 0 ;

    
do {front = (front + 1 ) % n;
       i
= cq[front];

       
if (i < pre)     // 分组
          {
           group
++ ;
           result[i
- 1 ] = group;
           
for (k = 0 ;k < n;k ++ ) newer[k] = r[i - 1 ][k];
          }

 

        
else   if (newer[i - 1 ] != 0 )    // 用冲突就放到下一组
            {
                rear
= (rear + 1 ) % n;
                cq[rear]
= i;
            }


        
else          // 无冲突就放入该组
            {
              result[i
- 1 ] = group;
              
for (k = 0 ;k < n;k ++ )
                 newer[k]
+= r[i - 1 ][k];
            }

        pre
= i;     // pre用来判断一轮是否搞完

    }
while (front != rear);
}


int  main()
// system("pause");
  int  a[N] = { 0 },r[N][N] = { 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
                  
1 , 0 , 0 , 0 , 1 , 1 , 0 , 1 , 1 ,
                  
0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 ,
                  
0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 1 ,
                  
0 , 1 , 0 , 1 , 0 , 1 , 1 , 0 , 1 ,
                  
0 , 1 , 1 , 0 , 1 , 0 , 1 , 0 , 0 ,
                  
0 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 ,
                  
0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
                  
0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 0 };
 
int  newer[N] = { 0 },result[N] = { 0 };

division(r,N,a,newer,result);    
// 函数调用
 
// system("pause");
for ( int  k = 0 ;k < N;k ++ )
a[k]
= k + 1 ;
// system("pause");
for (k = 1 ;k <= group;k ++ )     // 输出各组数据
{
       cout
<< " Group  " << k << " : " << endl; // system("pause");
    for ( int  j = 0 ;j < N;j ++ )
   { 
if (result[j] == k) cout << a[j] << "    " ;}
   cout
<< endl;
}
return  ( 0 );
}

 

队列应用举例--划分子集问题 - luojilie - luojilie的博客

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值