【路径寻找问题】UVa 10603 - Fill

Posted on 2015-03-02 23:14  LLGemini  阅读(188)  评论(0编辑  收藏  举报

如家大神书上的例题。第一次接触也是按代码敲得。敲的过程感觉很直观。但自己写估计会写的乱七八糟。以后不能砍得难就不愿意做这种题。否则只能做一些水题了。(PS:48)

紫书

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn = 205;
 8 struct Node
 9 {
10     int v[3];
11     int dist; //总倒水量
12     bool operator < (const Node& a) const
13     {
14         return dist > a.dist;
15     }
16 };
17 int vis[maxn][maxn], ans[maxn];
18 int cap[3];
19 void update_ans(const Node& u)
20 {
21     for(int i = 0; i < 3; i++)
22     {
23         int d = u.v[i]; //当前状态下每个杯的水量;
24         if(ans[d] < 0 || u.dist < ans[d])
25             ans[d] = u.dist;
26     }
27 }
28 void solve(int a, int b, int c, int d)
29 {
30     cap[0] = a; cap[1] = b; cap[2] = c;
31     memset(vis, 0, sizeof(vis));
32     memset(ans, -1, sizeof(ans));
33     priority_queue<Node> q; //优先队列应用!
34 
35     Node start;
36     start.v[0] = 0; start.v[1] = 0; start.v[2] = c; start.dist = 0;
37     q.push(start);
38 
39     vis[0][0] = 1;
40     while(!q.empty())
41     {
42         Node u = q.top(); q.pop(); //选择倒水量少的扩展
43         update_ans(u);
44         if(ans[d] >= 0) break;
45         for(int i = 0; i < 3; i++)
46             for(int j = 0; j < 3; j++)
47         {//把水从i倒入j
48             if(i == j) continue;
49             if(u.v[i] == 0 || u.v[j] == cap[j]) continue; //i没水或j满
50             int amount = min(cap[j], u.v[i]+u.v[j]) - u.v[j]; //从i倒入j中水的量
51             Node v;
52             memcpy(&v, &u, sizeof(u));
53             v.v[i] -= amount; v.v[j] += amount; v.dist += amount;
54             if(!vis[v.v[0]][v.v[1]]) //状态记忆;因总水量一定,故只知道其中两个杯子的水量就可知当前状态。故记忆数组用二维即可
55             {
56                 vis[v.v[0]][v.v[1]] = 1;
57                 q.push(v);
58             }
59         }
60     }
61     while(d >= 0) //若达不到,则尽可能接近
62     {
63         if(ans[d] >= 0)
64         {
65             printf("%d %d\n", ans[d], d);
66             return ;
67         }
68         d--;
69     }
70 }
71 int main()
72 {
73     int T; scanf("%d", &T);
74     while(T--)
75     {
76         int a, b, c, n;
77         scanf("%d%d%d%d", &a, &b, &c, &n);
78         solve(a, b, c, n);
79     }
80     return 0;
81 }

 

P205.直接上代码