很久没做ACM题了,最近又想做做,发现实力有待提高,这次做的题目不难,但也是在参考其他人的思路后做出来的,要继续努力。
题目:POJ 1753 Flip Game:http://acm.pku.edu.cn/JudgeOnline/problem?id=1753
学到的知识:1 BFS也可以用来求解最优问题,特别是在搜索问题的时候求解距离初始状态最短的路径,这个思想非常重要,要好好记住。
2 枚举,这次用的是枚举方法,奇怪的是,我一开始用的是c++的stl中的bitset和queue,但是却会溢出。。。,按照常理顶多65535个长度,不过不知道队列支持多大的就是,后来改成数组来当队列用就可以了。
感受:感觉做做ACM题对于训练思维和提升实际应用数据结构和算法的能力很有帮助,特别是数据结构,实际应用它和仅仅靠看书来对它进行理解完全是两码事,很多人说工作中几乎用不到算法和数据结构,对于这点我觉得那很有可能他们做得事都只设计很浅的层次,对计算机而言,真正的核心还是算法和数据结构,只有做到这个层次才能算深刻。
AC代码:
代码
1 #include <iostream>
2 #include <queue>
3
4 using namespace std;
5
6 int step[65535]; //记录步骤
7 bool flag[65535]; //防止重复搜索
8
9 unsigned short qState[65535]; //搜索的状态,正好可以用一个16位的无符号短整形表示
10 int rear = 0; //队列尾指针
11 int top = 0; //队列头指针
12
13 ///初始化:读入棋盘初始状态并把它转化为整数存入队列头,黑的位为1白的为0
14 void Init()
15 {
16 unsigned short temp = 0;
17 char c;
18
19 for(int i=0; i < 4; i++)
20 for(int j = 0; j < 4; j++)
21 {
22 cin>>c;
23 if('b' == c)
24 temp |= (1<<(i*4+j));
25 }
26
27 qState[rear++] = temp;
28 flag[temp] = true;
29 }
30
31 ///翻转一个棋子并按规则对齐周围棋子附加影响
32 unsigned short move(unsigned short state, int i)
33 {
34 unsigned short temp=0;
35 temp |= (1<<i);
36 if((i+1)%4 != 0) //右,且不在最右边
37 temp |= (1<<(i+1));
38 if(i%4 != 0) //左,且不在最左边
39 temp |= (1<<(i-1));
40 if(i+4 < 16) //下
41 temp |= (1<<(i+4));
42 if(i-4 >= 0) //上
43 temp |= (1<<(i-4));
44
45 return (state ^ temp);
46 }
47
48 //广度优先搜索,从队列中循环取出状态,并把翻转16次(即所有情况),一旦发现满足要求的立即停止,否则加入队列
49 bool BFS()
50 {
51 while(rear > top)
52 {
53 unsigned short state = qState[top++];
54 //qState.pop();
55 for(int i=0; i < 16; i++)
56 {
57 unsigned short temp;
58 temp = move(state,i);
59 if(0 == state || 65535 == state)
60 {
61 cout<<step[state];
62 return true;
63 }
64 else if(!flag[temp]) //防止重复搜索
65 {
66 //qState.push(temp);
67 qState[rear++] = temp;
68 flag[temp] = true;
69 step[temp] = step[state]+1;
70 }
71 }
72 }
73
74 return false;
75 }
76
77 int main(void)
78 {
79
80 Init();
81 if(!BFS()) cout<<"Impossible";
82
83 char c;
84 cin>>c;
85 }