题目一:幂集问题(组合问题) (参见《数据结构》(严蔚敏))
求含N个元素的集合的幂集。
如对于集合A={1,2,3},则A的幂集为
p(A)={{1,2,3},{1,2},{1,3},{1},{2,3},{2},{3},Φ}
幂集的每个元素是一个集合,它或是空集,或含集合A中的一个元素,或含A中的两个元素,或者等于集合A。反之,集合A中的每一个元素,它只有两种状态:属于幂集的元素集,或不属于幂集元素集。则求幂集P(A)的元素的过程可看成是依次对集合A中元素进行“取”或“舍”的过程,并且可以用一棵状态树来表示。求幂集元素的过程即为先序遍历这棵状态树的过程。
求含N个元素的集合的幂集。
如对于集合A={1,2,3},则A的幂集为
p(A)={{1,2,3},{1,2},{1,3},{1},{2,3},{2},{3},Φ}
幂集的每个元素是一个集合,它或是空集,或含集合A中的一个元素,或含A中的两个元素,或者等于集合A。反之,集合A中的每一个元素,它只有两种状态:属于幂集的元素集,或不属于幂集元素集。则求幂集P(A)的元素的过程可看成是依次对集合A中元素进行“取”或“舍”的过程,并且可以用一棵状态树来表示。求幂集元素的过程即为先序遍历这棵状态树的过程。
#include <stdio.h>
#include <malloc.h>
#define ERROR 0
#define OK 1
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode,*LinkList;
//初始化
LinkList ListInit()
{
LNode *base=(LinkList)malloc(sizeof(LNode));
base->data=0;
base->next=NULL;
return base;
}
//插入一个元素
int ListInsert(LinkList L,int i,ElemType e)
{
LNode *p,*s;
int j=0;
p=(LNode *)L;
while(p&&j<i-1)
{
p=p->next;
++j;
}
if(!p||j>i-1)
return ERROR;
s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
//删除一个结点
int ListDelete(LinkList &L,int i,ElemType &e)
{
LinkList p=L,q;
int j=0;
while(p->next&&j<i-1)
{
p=p->next;
++j;
}
if(!(p->next)||j>i-1)
return ERROR;
q=p->next;
p->next=q->next;
e=q->data;
free(q);
}
//长度
int ListLength(LinkList L)
{
LinkList p=L;
int j=0;
if(!L)
return ERROR;
while(p->next)
{
p=p->next;
++j;
}
return j;
}
//查找一个元素
int GetElem(LinkList L,int i,ElemType &e)
{
LNode *p=L;
int j=0;
while(p->next&&j<i)
{
p=p->next;
++j;
}
if(!p||j>i)
return ERROR;
e=p->data;
return OK;
}
//输出链表元素
void Display(LinkList L)
{
LNode *p=L;
if(!(p->next))
{
printf("NULL,");
return;
}
else
p=p->next;
while(p)
{
printf("%d,",p->data);
p=p->next;
}
}
//求幂集
void PowerSet(int i,LinkList A,LinkList &B)
{
int k=0;
ElemType e=0;
if(i>ListLength(A))
{
Display(B);
printf("\n");
}
else
{
GetElem(A,i,e);
k=ListLength(B);
ListInsert(B,k+1,e); //取
PowerSet(i+1,A,B);
ListDelete(B,k+1,e); //舍
PowerSet(i+1,A,B);
}
}
int main()
{
LinkList list=ListInit(); //初始化
LinkList list2=ListInit();//初始化
ListInsert(list,1,1);//插入元素
ListInsert(list,2,2);
ListInsert(list,3,3);
Display(list);//输出元素
printf("\npower set is:\n");
PowerSet(1,list,list2);//求幂集
}
题目二:求 4 皇后问题的所有合法布局(作为例子,我们将8皇后问题简化为4皇后)
我们从空棋盘开始,然后把皇后1放到它所在行的第一个可能位置上,也就是第一行第—列。对于皇后2,在经过第一列和第二列的失败尝试之后,我们把它放在第一个可能的位置,就是格子〔2,3),位于第二行第二列的格子。这被证明是一个死胡同,因为皇后:将没有位置可放。所以,该算法进行回溯,把皇后2放在下一个可能位置(2,4)上。然后皇后3就可以放在(3,2),这被证明是另一个死胡同。该算法然后就回溯到底,把皇后1移到(1,2)。接着皇后2到(2,4),皇后3到(3,1),而皇后4到(4,3),这就是该问题的一个解。图2给出了这个查找的状态空间树。
#include <stdio.h>
#include <math.h>
#define N 4
int col[N+1];
//输出结果
void Output()
{
for(int i=1;i<=N;i++)
{
printf("(%d,%d)\n",i,col[i]);
}
printf("\n");
}
//求解函数
void Queen(int i,int n)
{ //进入本函数时,在n*n棋盘前 i-1 行已经放置了互不攻击的 i-1 个棋子
//现在从第 i 行起继续为后续棋子选择合适的位置
//当 i>n 时,求得一个合法的布局,则输出
if(i>n)
Output();
else
{
for(int j=1;j<=n;++j)
{
int k=1;
col[i]=j; //第 i 行的第 j 列放置一个棋子
while(k<i) //判断是否放置合法
{ //fabs是取绝对值
if((col[k]-col[i])*(fabs(col[k]-col[i])-fabs(k-i))!=0)
{
k++;
if(k==i)
Queen(i+1,n);
}
else
{
break;
}
}
}
}
}
void main()
{
printf("the answer is:\n");
for(int i=1;i<=N;i++)
{
col[1]=i; //设置第一行
Queen(2,N);
}
}
转载自:http://www.cnblogs.com/hustcat/archive/2008/04/09/1144645.html