经过一天的奋斗,解决~~~ ^_^
![队列应用举例--划分子集问题 - luojilie - luojilie的博客 队列应用举例--划分子集问题 - luojilie - luojilie的博客](http://img776.ph.126.net/TTM8u4RcMenPftCo-s0vZA==/3124653716466069861.jpg)
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的博客 队列应用举例--划分子集问题 - luojilie - luojilie的博客](http://img.ph.126.net/UXPTXf_9ETLCJhQBE4bJGw==/28428972664632442.jpg)
// 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的博客 队列应用举例--划分子集问题 - luojilie - luojilie的博客](http://img776.ph.126.net/TTM8u4RcMenPftCo-s0vZA==/3124653716466069861.jpg)