状态空间搜索好题UVA10603

题目

分析:注意这里求的是最少流量, 二不是最少步数!!!所以我们用优先队列去维护一个最小流量,然后进行bfs即可,解释一下一个重要的数组ans[i],表示的是杯子中的水为i时的最小流量

 1 #include "iostream"
 2 #include "cstdio"
 3 #include "cstring"
 4 #include "queue"
 5 #include "algorithm"
 6 using namespace std;
 7 const int maxn=200+10;
 8 int a,b,c,d,T;
 9 int vis[maxn][maxn],ans[maxn],cap[3];  //ans[i]表示杯子中有i升水时对应的最少倒水量
10 struct Node{
11     int v[3],dist;
12     bool operator < (const Node & rsh) const{  //小顶堆
13         return dist>rsh.dist;
14     }
15 };
16
17 void update(const Node & u){   //更新ans[]
18     for(int i=0;i<3;i++){
19         int s=u.v[i];
20         if(ans[s]<0||u.dist<ans[s])  ans[s]=u.dist;
21     }
22 }
23
24 void bfs(int a,int b,int c,int d){
25     memset(vis,0,sizeof(vis));
26     memset(ans,-1,sizeof(ans));
27     cap[0]=a,cap[1]=b,cap[2]=c;
28     Node start;
29     start.dist=0;
30     start.v[0]=0,start.v[1]=0,start.v[2]=c;
31     priority_queue<Node>que;
32     vis[0][0]=1;
33     que.push(start);
34     while(!que.empty()){
35         Node u=que.top(); que.pop();
36         update(u);
37         if(ans[d]>=0)  break;   //如果找到了
38         for(int i=0;i<3;i++){
39             for(int j=0;j<3;j++) if(i!=j){   //自己不能和自己匹配
40                 if(u.v[i]==0||u.v[j]==cap[j])   continue;
41                 int num=min(cap[j],u.v[i]+u.v[j])-u.v[j];
42                 Node u2;
43                 memcpy(&u2,&u,sizeof(u));
44                 u2.v[i]-=num;
45                 u2.v[j]+=num;
46                 u2.dist=u.dist+num;
47                 if(!vis[u2.v[0]][u2.v[1]]){  //如果当前状态没有出现过
48                     vis[u2.v[0]][u2.v[1]]=1;
49                     que.push(u2);
50                 }
51             }
52         }
53     }
54     while(d>=0){
55         if(ans[d]>=0){
56             printf("%d %d\n",ans[d],d);
57             return ;
58         }
59         --d;
60     }
61 }
62 int main()
63 {
64     scanf("%d",&T);
65     while(T--){
66         scanf("%d%d%d%d",&a,&b,&c,&d);
67         bfs(a,b,c,d);
68     }
69     return 0;
70 }

时间: 2024-11-05 16:24:02

状态空间搜索好题UVA10603的相关文章

POJ 1979 Red and Black 深度优先搜索上手题

Red and Black Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21738   Accepted: 11656 Description There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a

UVa 11212 Editing a Book (IDA* &amp;&amp; 状态空间搜索)

题意:你有一篇n(2≤n≤9)个自然段组成的文章,希望将它们排列成1,2,-,n.可以用Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务.每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴.注意,剪贴板只有一个,所以不能连续剪切两次,只能剪切和粘贴交替.例如,为了将{2,4,1,5,3,6}变为升序,可以剪切1将其放到2前,然后剪切3将其放到4前.再如,排列{3,4,5,1,2},只需一次剪切和一次粘贴即可--将{3,4,5}放在{1,2}后,或者将{1,2}放在{3,4,5}前. 分析

UVa 1343 The Rotation Game (状态空间搜索 &amp;&amp; IDA*)

题意:有个#字型的棋盘,2行2列,一共24个格. 如图:每个格子是1或2或3,一共8个1,8个2,8个3. 有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面. 求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字.如果有多个解,输出字典序最小的操作步骤. 分析 : 还是状态空间的搜索,对象就是一个数字序列,判断中心位置是否一样,可以看出如果使用BFS,每一层还是爆炸,所以使用IDA*,关键还是模拟操作和h函数,这里的h函数是这样定义的,

华为题 搜索水题 DFS

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <string> 6 #include <iterator> 7 #include <algorithm> 8 #include <cstdlib> 9 #include <deque> 10 #include &l

HDU 1142 A Walk Through the Forest (Dijkstra + 记忆化搜索 好题)

A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6350    Accepted Submission(s): 2332 Problem Description Jimmy experiences a lot of stress at work these days, especial

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&amp;&amp;NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床发现194了然后就各种刷--当我发现199的时候我决定把第200题交给05年NOI仅剩的一道题--结果尼玛调了能有一个小时--我居然没看到编号最小这个限制0.0 首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行单调递减 于是我们记忆化搜索 首先用

搜索基础题

1.http://acm.hdu.edu.cn/showproblem.php?pid=1312 题意:在一个仅有红黑格子组成的矩形中,一个人只能走上下左右相邻黑色格子,问从起点开始共能走多少个格子? ’#‘:红色格子 ’.': 黑色格子: ’@‘:起点 BFS 和 DFS 都可以遍历所有走的点,每次走过一点时,计数++即可: 2.http://acm.hdu.edu.cn/showproblem.php?pid=1728 由题可知,在限制转弯数量的前提下 能够从一点走到另一个点即可:BFS 和

搜索刷题记录

我好菜啊!连暴搜都不会! 注意边界退出! 特开此帖,记录搜索学习之路!(逃) 1.全排列 2.八皇后 3.数的划分 由于此题有同一划分方法算一个的限制,我们为了避免搜多,可以使搜出的结果满足单调不降性,那么就要在dfs时传一个pre参数. 由于要使划分后数之和为n,记录当前搜的总值sum. 由于有划分k个的限制,记录当前搜出了几个. 小总结,dfs函数的参数由其限制条件得出. 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9368382.htm

hdu4845 状态压缩搜索水题

这道题简单来说是和胜利大逃亡续类似的题  只不过这道题没有给你明确的地图 只给了你点之间的关系          唯一的坑点在于一个点可能有多把钥匙 #include<stdio.h> #include<string.h> #include<iostream> #include<queue> using namespace std; struct node { int x,y,step,state; }a,b; int mark[16][16][3030];