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. 不断执行Step2,Step3和Step4,直到队列为空,停止程序,此时未找到可行的解,则该问题无解。
#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*/
阅读全文
0 0
- BFS解决一般性的泊松分酒问题
- 一般性问题的解决方法
- I2C总线的一般性问题
- sql server2000 安装过程中"一般性网络错误"问题的解决
- Memcached FAQ(1) 一般性的问题
- Memcached FAQ(1) 一般性的问题
- Memcached FAQ(1) 一般性的问题
- Memcached FAQ(1) 一般性的问题
- H∞鲁棒控制问题的一般性描述
- 迷宫问题bfs解决
- “GDI+中发生一般性错误” 的终极解决
- 一般性编程问题
- OpenCV一般性问题
- Richeidt一般性问题
- sql server一般性问题
- I2C通信一般性问题
- iOS面试一般性问题
- iOS面试一般性问题
- 1004. 成绩排名 (20)
- 仿微信的录制小视频功能
- 蓝桥杯决赛----加法变乘法
- Hibernate 关系关联映射和cascade与inverse
- 网站高并发 大流量访问的处理及解决方法
- BFS解决一般性的泊松分酒问题
- hdoj1027 Ignatius and the Princess II(全排列)
- 权限模型
- Alphago二胜有感
- 编程之美2.5 寻找最大的K个数
- 【Linux多线程】同步与互斥的区别
- JSP 猜字母游戏
- 百度地图与廊坊交警宣布合作 打造华北区“智慧出行”又一模范城市
- 爬虫之爬取知乎下某个问题下的全部图片(处理AJAX请求,解析json数据)