uva 704

自己之前的不见了。。

这题是双向广搜即可过。。

  1 // Colour Hash (色彩缤纷游戏)
  2 // PC/UVa IDs: 110807/704, Popularity: B, Success rate: average Level: 3
  3 // Verdict: Accepted
  4 // Submission Date: 2011-08-28
  5 // UVa Run Time: 0.048s
  6 //
  7 // 版权所有(C)2011,邱秋。metaphysis # yeah dot net
  8 //
  9 // 若从给定状态进行单向搜索,由于状态较多,容易 TLE,故采用双向搜索的办法,逆向搜索:从目标状态
 10 // 搜索 8 步,把所有得到的结果记录在集合 A 中;正向搜索:从给定状态搜索 9 步,若在搜索过程中生成
 11 // 的某个状态在集合 A 中,则表明在 16 步内能找到解,否则无法找到解。
 12 //
 13 // 这里较为关键的是如何表示游戏的当前状态,以避免在集合 A 中添加重复的状态,可以使用字符串来表示
 14 // 当前的滑块状态。集合 A 可以使用 map 来判断是否已经有重复的状态产生。
 15
 16 #include <iostream>
 17 #include <queue>
 18 #include <map>
 19
 20 using namespace std;
 21
 22 #define LEFT_CLOCKWISE 1        // 左侧顺时针。
 23 #define RIGHT_CLOCKWISE 2        // 右侧顺时针。
 24 #define LEFT_COUNTERCLOCKWISE 3        // 左侧逆时针。
 25 #define RIGHT_COUNTERCLOCKWISE 4    // 右侧逆时针。
 26
 27 #define NWHEEL 24        // 滑块总数目。
 28 #define HALF_WHEEL 9        // 左侧滑块的数目。
 29 #define MIDDLE_WHEEL 3        // 中间滑块的数目。
 30 #define BACKWARD_DEPTH 8    // 逆向搜索深度。
 31
 32 // 目标状态。存储方式为左侧滑块-右侧滑块-中间滑块,因为编号为 10 的滑块占两个字符,故用 10 的英
 33 // 文(ten)首字母 T 来表示。
 34 string target = "034305650078709T90121";
 35
 36 // 逆向搜索的缓存,使用字符串来表示状态和旋转序列。
 37 map < string, string > cache;
 38
 39 // 旋转操作的逆。1 的逆为 3,2 的逆为 4,依此类推。
 40 int reverse[4] = { 3, 4, 1, 2 };
 41
 42 // 表示滑块当前状态的结构。
 43 struct node
 44 {
 45     string config;        // 滑块状态。
 46     string sequences;    // 到达此位置的旋转序列。
 47 };
 48
 49 // 按指定的方向旋转滑块。
 50 void rotate(string &config, int direction)
 51 {
 52     // 获取中间滑块部分。
 53     string middle = config.substr(HALF_WHEEL * 2);
 54
 55     switch (direction)
 56     {
 57             // 左侧滑块顺时针旋转。
 58         case LEFT_CLOCKWISE:
 59
 60             config[HALF_WHEEL * 2] = config[HALF_WHEEL - 2];
 61             config[HALF_WHEEL * 2 + 1] = config[HALF_WHEEL - 1];
 62             config[HALF_WHEEL * 2 + 2] = middle[0];
 63
 64             for (int i = HALF_WHEEL - 1; i >= 2; i--)
 65                 config[i] = config[i - 2];
 66             config[1] = middle[2];
 67             config[0] = middle[1];
 68
 69             break;
 70
 71             // 右侧滑块顺时针旋转。
 72         case RIGHT_CLOCKWISE:
 73
 74             config[HALF_WHEEL * 2] = middle[2];
 75             config[HALF_WHEEL * 2 + 1] = config[HALF_WHEEL];
 76             config[HALF_WHEEL * 2 + 2] = config[HALF_WHEEL + 1];
 77
 78             for (int i = HALF_WHEEL; i <= (HALF_WHEEL * 2 - 3); i++)
 79                 config[i] = config[i + 2];
 80             config[HALF_WHEEL * 2 - 2] = middle[0];
 81             config[HALF_WHEEL * 2 - 1] = middle[1];
 82
 83             break;
 84
 85             // 左侧滑块逆时针旋转。
 86         case LEFT_COUNTERCLOCKWISE:
 87
 88             config[HALF_WHEEL * 2] = middle[2];
 89             config[HALF_WHEEL * 2 + 1] = config[0];
 90             config[HALF_WHEEL * 2 + 2] = config[1];
 91
 92             for (int i = 0; i <= HALF_WHEEL - 3; i++)
 93                 config[i] = config[i + 2];
 94             config[HALF_WHEEL - 2] = middle[0];
 95             config[HALF_WHEEL - 1] = middle[1];
 96
 97             break;
 98
 99             // 右侧滑块逆时针旋转。
100         case RIGHT_COUNTERCLOCKWISE:
101
102             config[HALF_WHEEL * 2] = config[HALF_WHEEL * 2 - 2];
103             config[HALF_WHEEL * 2 + 1] = config[HALF_WHEEL * 2 - 1];
104             config[HALF_WHEEL * 2 + 2] = middle[0];
105
106             for (int i = 2 * HALF_WHEEL - 1; i >= HALF_WHEEL + 2; i--)
107                 config[i] = config[i - 2];
108             config[HALF_WHEEL + 1] = middle[2];
109             config[HALF_WHEEL] = middle[1];
110
111             break;
112     }
113 }
114
115 // 从目标状态生成 8 步内所有可能产生的状态,使用宽度优先搜索的方法,用 map 存储生成的状态和相应
116 // 的旋转序列。
117 void backward_search(string config)
118 {
119     queue <node> open;
120
121     node tmp;
122     tmp.config = config;
123     tmp.sequences = "";
124
125     open.push(tmp);
126
127     while (!open.empty())
128     {
129         node copy = open.front();
130         open.pop();
131
132         // 当扩展的深度达到 8 层后停止在此状态上继续扩展。
133         if (copy.sequences.length() >= BACKWARD_DEPTH)
134             continue;
135
136         for (int i = LEFT_CLOCKWISE; i <= RIGHT_COUNTERCLOCKWISE; i++)
137         {
138             // 跳过无效的移动,例如前一步采用了左侧顺时针旋转,则当前若使用
139             // 左侧逆时针旋转会回到上一步的状态。
140             if (copy.sequences.length() > 0)
141             {
142                 // 注意使用的是旋转操作的逆,故需还原后判断。
143                 int last_rotate = reverse[copy.sequences[0] - ‘0‘ - 1];
144                 if (last_rotate != i && ((last_rotate + i) == 4 ||
145                                                                 (last_rotate + i) == 6))
146                     continue;
147             }
148
149             string t = copy.config;
150             rotate(t, i);
151
152             if (cache.find(t) == cache.end())
153             {
154                 node successor;
155                 successor.config = t;
156                 // 记录逆向搜索的旋转序列时,使用当前旋转的逆。
157                 successor.sequences = (char)(‘0‘ + reverse[i - 1]) + copy.sequences;
158                 open.push(successor);
159
160                 cache.insert(make_pair<string, string>(t, successor.sequences));
161             }
162         }
163     }
164 }
165
166 // 进行正向搜索,采用宽度优先搜索模式。
167 bool forward_search(string config)
168 {
169     queue <node> open;
170
171     node tmp;
172     tmp.config = config;
173     tmp.sequences = "";
174
175     open.push(tmp);
176
177     while (!open.empty())
178     {
179         node copy = open.front();
180         open.pop();
181
182         // 已经找到在缓存中的状态,输出旋转序列。
183         if (cache.find(copy.config) != cache.end())
184         {
185             cout << copy.sequences;
186             map <string, string>::iterator it = cache.find(copy.config);
187             cout << (*it).second << endl;
188
189             return true;
190         }
191
192         // 搜索深度为 9。
193         if (copy.sequences.length() >= (BACKWARD_DEPTH + 1))
194             continue;
195
196         for (int i = LEFT_CLOCKWISE; i <= RIGHT_COUNTERCLOCKWISE; i++)
197         {
198             // 若前后两步构成互补状态则跳过。
199             if (copy.sequences.length() > 0)
200             {
201                 int size = copy.sequences.length();
202                 int last_rotate = copy.sequences[size - 1] - ‘0‘;
203                 if (last_rotate != i && ((last_rotate + i) == 4 ||
204                                                                 (last_rotate + i) == 6))
205                     continue;
206             }
207
208             string t = copy.config;
209             rotate(t, i);
210
211             node successor;
212             successor.config = t;
213             successor.sequences = copy.sequences + (char)(‘0‘ + i);
214
215             open.push(successor);
216         }
217     }
218
219     return false;
220 }
221
222 // 和目标状态比较,确定是否为已解决状态。
223 bool solved(string config)
224 {
225     for (int i = 0; i < target.length(); i++)
226         if (config[i] != target[i])
227             return false;
228
229     return true;
230 }
231
232 int main(int ac, char *av[])
233 {
234     string config;
235     int c;
236     int cases;
237
238     // 先生成逆向搜索的结果以备查。
239     backward_search(target);
240
241     cin >> cases;
242     while (cases--)
243     {
244         // 读入初始状态。
245         config.clear();
246         for (int i = 0; i < NWHEEL; i++)
247         {
248             cin >> c;
249             if (c == 10)
250                 config.append(1, ‘T‘);
251             else
252                 config.append(1, c + ‘0‘);
253         }
254
255         // 调整表示形式。
256         config = config.substr(0, HALF_WHEEL) +
257             config.substr(HALF_WHEEL + MIDDLE_WHEEL, HALF_WHEEL) +
258             config.substr(2 * HALF_WHEEL + MIDDLE_WHEEL);
259
260         // 先判断是否已经为解决状态。
261         if (solved(config))
262         {
263             cout << "PUZZLE ALREADY SOLVED" << endl;
264             continue;
265         }
266
267         // 进行正向搜索查找。
268         if (!forward_search(config))
269             cout << "NO SOLUTION WAS FOUND IN 16 STEPS" << endl;
270     }
271
272     return 0;
273 }

uva 704

时间: 2024-10-08 18:01:53

uva 704的相关文章

Colour Hash (Uva 704 双向bfs)

Colour Hash Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description This puzzle consists of two wheels. Both wheels can rotate both clock and counter-clockwise. They contain 21 coloured pieces, 10 of which

编程题目分类(剪辑)

1. 编程入门 2. 数据结构 3. 字符串 4. 排序 5. 图遍历 6. 图算法 7. 搜索:剪枝,启发式搜索 8. 动态规划/递推 9. 分治/递归 10. 贪心 11. 模拟 12. 算术与代数 13. 组合问题 14. 数论 15. 网格,几何,计算几何 [编程入门] PC 110101, uva 100, The 3n+1 problem, 难度 1 PC 110102, uva 10189, Minesweeper, 难度 1 PC 110103, uva 10137, The T

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f

[UVa] Palindromes(401)

UVA - 401 Palindromes Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description A regular palindrome is a string of numbers or letters that is the same forward as backward. For example, the string "ABCDED

uva 401.Palindromes

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=342 题目意思:给出一段字符串(大写字母+数字组成).判断是否为回文串 or 镜像串 or 回文镜像串 or 什么都不是.每个字母的镜像表格如下 Character Reverse Character Reverse Character Reverse A A M M Y Y B

[2016-02-19][UVA][129][Krypton Factor]

UVA - 129 Krypton Factor Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description You have been employed by the organisers of a Super Krypton Factor Contest in which contestants have very high mental and physica

[2016-02-03][UVA][514][Rails]

时间:2016-02-03 22:24:52 星期三 题目编号:UVA 514 题目大意:给定若干的火车(编号1-n),按1-n的顺序进入车站, 给出火车出站的顺序,问是否有可能存在 分析:    FIFO,用栈模拟一遍即可, 方法:    根据输入的顺序,从1-n开始,当前操作的为i 如果i是当前对应的编号,那么直接跳过(进入B) 如果不是,根据当前需求的编号,小于i,就从栈顶弹出一个元素, 看这个元素是否是需求的,是则继续.否则NO 1 2 3 4 5 6 7 8 9 10 11 12 13