BFS解决一般性的泊松分酒问题

来源:互联网 发布:三菱plc fx编程手册 编辑:程序博客网 时间:2024/06/08 10:45
BFS解决一般性的泊松分酒问题

  有一只装满8斤酒的瓶子和两只分别装5斤和3斤酒的空瓶,如何才能将这8斤酒分为两等份。这个问题规模小,手工就可以完成。那么更大规模和一般性的问题又如何解决呢? 

  通过广度优先搜索(BFS)对状态空间进行逐步搜索,若能找到答案,则为最少步数解,反之则无解。具体过程如下:

      设共有n个瓶子,最大容量分别为(x1,x2,...,xn),则共有(x1+1)(x2+1)...(xn+1)种可能的状态,搜索空间过于庞大。但考虑到瓶子的容量差,在倒酒的过程中不可能出现所有的情况。因此要对新加入图中的状态进行判断,即剪枝,如果新生成的状态是可行的,将其加入图中,反之将其舍弃。在广度优先搜索的过程中,使用一个队列Q存储新生成的状态,一个数组Visited存储出现过的状态。搜索过程如下所示

Step1. 将初始状态(x10,x20,...,xn0)加入到队列Q以及Visited数组中。

Step2. 将队列Q队头的状态出队列,找出Q可能生成的状态。

Step3. 判断新生成的状态是否为目标状态,若是,则停止搜索,若不是,继续执行Step4。

Step4. 判断新生成的状态是否位于Visited数组中,若已存在则跳过该状态判断下一状态。若未存在则将其加入到队列Q尾部,并加入到Visited数组中,并判断下一个状态。

Step4. 不断执行Step2Step3Step4,直到队列为空,停止程序,此时未找到可行的解,则该问题无解。

#include<stdio.h>#include<stdlib.h>#include<windows.h>#define TRUE 1#define FASLE 0#define MAXSIZE 100000typedef struct{int **rear,**front;int Queuelen;}Queue;void InitQueue(Queue &Q, int n){Q.rear = Q.front = (int**)malloc(sizeof(int*) * MAXSIZE);for(int i = 0; i < MAXSIZE; i++){Q.rear[i] = Q.front[i] = (int*)malloc(sizeof(int) * n);}Q.Queuelen = 0;}void EnQueue(Queue &Q,int* e){*(Q.rear++) = e;}void DeQueue(Queue &Q,int* &e){e = *(Q.front++);}int QueueEmpty(Queue Q){if(Q.front == Q.rear)    return TRUE;else    return FASLE;}void pour(const int* status, const int* volume, int i, int j,int* new_volume, int n){for(int k = 0; k < n; k++){new_volume[k] = status[k];}if(new_volume[i] + new_volume[j] <= volume[j]){new_volume[j] += new_volume[i];new_volume[i] = 0;}else{new_volume[i] -= (volume[j] - new_volume[j]);new_volume[j] = volume[j];}}int exist(int** visited, int* new_volume,int n, int num){int flag;for(int i = 0; i < num; i++){flag = 1;for(int j = 0; j < n; j++){if(visited[i][j] != new_volume[j]){flag = 0;break;}}if(flag)    break;}return flag;}void append(int** &visited, int &num, int* new_volume, int n){for(int i = 0; i < n; i++){visited[num][i] = new_volume[i];}num++;}int achieve(const int* target, const int* new_volume, int n){int flag = 1;for(int i = 0; i < n; i++){if(target[i] != new_volume[i]){flag = 0;break; }}return flag;}void print(const int* current_volume, int* new_volume, int n){for(int i = 0; i < n - 1; i++){printf("%d,",current_volume[i]);}printf("%d",current_volume[n - 1]);printf("---");for(int i = 0; i < n - 1; i++){printf("%d,",new_volume[i]);}printf("%d\n",new_volume[n - 1]);}void copy_volume(const int* new_volume, int* copy, int n){for(int k = 0; k < n; k++){copy[k] = new_volume[k];}}void BFS(int* volume, int* current_volume, int n, int* target){Queue Q;InitQueue(Q,n);    EnQueue(Q, current_volume);int num = 0;int** visited;visited = (int**)malloc(sizeof(int*) * MAXSIZE);for(int i = 0; i < MAXSIZE; i++){visited[i] = (int*)malloc(sizeof(int) * n);}append(visited, num, current_volume, n);int* status = (int*)malloc(sizeof(int) * n);int* new_volume = (int*)malloc(sizeof(int) * n);int layer = 0;int* copy;int qlen[MAXSIZE]; qlen[layer] = 1;int achieved = 0;while(!QueueEmpty(Q)){DeQueue(Q, status);for(int i = 0; i < n; i++){if(status[i] != 0){for(int j = 0; j < n; j++){if(j == i){//j--;continue;}if(status[j] == volume[j])    continue;pour(status, volume, i, j, new_volume, n);copy = (int*)malloc(sizeof(int) * n);copy_volume(new_volume, copy, n);if(exist(visited, copy, n, num))    continue;else{print(status, copy, n);if(achieve(target, new_volume, n)){printf("已找到答案!    ");printf("当前第%d层--------------------------\n",layer + 1);system("pause");achieved = 1;}    append(visited, num, copy, n);EnQueue(Q, copy);}}}}qlen[layer]--;if(!qlen[layer]){printf("第%d层遍历完毕--------------------------\n",layer + 1);    layer++;    qlen[layer] = Q.rear - Q.front;}}if(!achieved)    printf("未找到答案!    ");printf("搜索完毕\n***************************************\n\n"); }int main(){int n;while(1){printf("请输入瓶子个数\n"); scanf("%d",&n);int* volume;int* current_volume;    int* target;    target = (int*)malloc(sizeof(int) * n);    volume = (int*)malloc(sizeof(int) * n);    current_volume = (int*)malloc(sizeof(int) * n);int step = 0;printf("请输入各个瓶子的最大容量\n"); for(int i = 0; i < n; i++){scanf("%d",&volume[i]);}printf("请输入各个瓶子的当前容量\n"); for(int i = 0; i < n; i++){scanf("%d",¤t_volume[i]);}printf("请输入各个瓶子的目标容量\n"); for(int i = 0; i < n; i++){scanf("%d",&target[i]);}BFS(volume, current_volume, n, target);}return 0;} /*38 5 38 0 04 4 0*/







原创粉丝点击