【wikioi】1004 四子连棋

题目链接

算法:BFS

//2014-02-05更新

*******************************2013-10-15*******************************

PS:被卡过2天。日期:2013-10-14 ~ 2013-10-15 17:28:21

此题卡了我一天,原因是宽搜时方向搞错= =(汗= =),而这个错误我竟然检查了好久= =!!

(大神不要笑,我用来超多的代码来实现= =是别人提交代码的5倍以上,,,200多行= =)

2014.01.02 PS: 我承认我是脑残了,现在已会写bfs,改天有时间修改下,下面这个程序很好的证明了我不会搜索= =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include <iostream>
#include <cstring>
#include <queue>
 
using namespace std;
enum pa{NUL, LEFT, UP, RIGHT, DOWN};    //四个方向
enum color{O, W, B};                    //白色用W表示,黑色用B表示,NUL就表示空格
struct st
{
    color m[4][4];
    short d;                //次数
    short x1, y1, x2, y2;   //空格的位置
    bool who;               //0表示到白棋走,1表示黑棋走
    pa p1, p2;              //空格之前所在的位置,即以本格子来看从哪个位置是移动之前的状态
    st& operator= (const st& s)
    {
        memcpy(m, s.m, sizeof(m));
        d=s.d; who=s.who;
        p1=s.p1; p2=s.p2;
        x1=s.x1; x2=s.x2;
        y1=s.y1; y2=s.y2;
        return *this;
    }
    st(){memset(m, 0, sizeof(m)); d=0; x1=x2=y1=y2=-1; p1=p2=NUL; who=1;}
}state;
queue<st> q;
int i, j;
 
void readin()
{
    char chartemp;
    for(i = 0; i < 4; i++) for(j = 0; j < 4; j++)
    {
        cin >> chartemp;
        if(chartemp == 'W') state.m[i][j] = W;
        else if(chartemp == 'B') state.m[i][j] = B;
        else
        {
            state.m[i][j] = O;
            if(state.x1 == -1)
                state.x1 = i, state.y1 = j;
            else
                state.x2 = i, state.y2 = j;
        }
    }
}
 
void chu()
{
    st t = state;
    if(t.x1+1<4 && t.m[t.x1+1][t.y1] != O) //第一个空格 向下移
    {
        t.p1 = UP; t.p2 = NUL;
        t.x1++; t.m[t.x1-1][t.y1] = t.m[t.x1][t.y1];
        t.m[t.x1][t.y1] = O; t.d++;
        t.who = t.m[t.x1-1][t.y1]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.x2+1<4 && t.m[t.x2+1][t.y2] != O) //第二个空格 向下移
    {
        t.p2 = UP; t.p1 = NUL;
        t.x2++; t.m[t.x2-1][t.y2] = t.m[t.x2][t.y2];
        t.m[t.x2][t.y2] = O; t.d++;
        t.who = t.m[t.x2-1][t.y2]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.y1+1<4 && t.m[t.x1][t.y1+1] != O) //第一个空格 向右移
    {
        t.p1 = LEFT; t.p2 = NUL;
        t.y1++; t.m[t.x1][t.y1-1] = t.m[t.x1][t.y1];
        t.m[t.x1][t.y1] = O; t.d++;
        t.who = t.m[t.x1][t.y1-1]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.y2+1<4 && t.m[t.x2][t.y2+1] != O) //第二个空格 向右移
    {
        t.p2 = LEFT; t.p1 = NUL;
        t.y2++; t.m[t.x2][t.y2-1] = t.m[t.x2][t.y2];
        t.m[t.x2][t.y2] = O; t.d++;
        t.who = t.m[t.x2][t.y2-1]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.x1 > 0 && t.m[t.x1-1][t.y1] != O) //第一个空格 向上移
    {
        t.p1 = DOWN; t.p2 = NUL;
        t.x1--; t.m[t.x1+1][t.y1] = t.m[t.x1][t.y1];
        t.m[t.x1][t.y1] = O; t.d++;
        t.who = t.m[t.x1+1][t.y1]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.x2 > 0 && t.m[t.x2-1][t.y2] != O) //第二个空格 向上移
    {
        t.p2 = DOWN; t.p1 = NUL;
        t.x2--; t.m[t.x2+1][t.y2] = t.m[t.x2][t.y2];
        t.m[t.x2][t.y2] = O; t.d++;
        t.who = t.m[t.x2+1][t.y2]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.y1 > 0 && t.m[t.x1][t.y1-1] != O) //第一个空格 向左移
    {
        t.p1 = RIGHT; t.p2 = NUL;
        t.y1--; t.m[t.x1][t.y1+1] = t.m[t.x1][t.y1];
        t.m[t.x1][t.y1] = O; t.d++;
        t.who = t.m[t.x1][t.y1+1]-1; t.who = !t.who;
        q.push(t);
    }
    t = state;
    if(t.y2 > 0 && t.m[t.x2][t.y2-1] != O) //第二个空格 向左移
    {
        t.p2 = RIGHT; t.p1 = NUL;
        t.y2--; t.m[t.x2][t.y2+1] = t.m[t.x2][t.y2];
        t.m[t.x2][t.y2] = O; t.d++;
        t.who = t.m[t.x2][t.y2+1]-1; t.who = !t.who;
        q.push(t);
    }
}
 
bool check(const st& s)
{
    int x, y; pa p; bool bp = 1;
    if(s.p1 != NUL) p = s.p1; else {p = s.p2; bp = 0;}
    switch(p)
    {
        case UP:
            x = (bp?s.x1-1:s.x2-1); y = (bp?s.y1:s.y2);
            break;
        case DOWN:
            x = (bp?s.x1+1:s.x2+1); y = (bp?s.y1:s.y2);
            break;
        case RIGHT:
            x = (bp?s.x1:s.x2); y = (bp?s.y1+1:s.y2+1);
            break;
        case LEFT:
            x = (bp?s.x1:s.x2); y = (bp?s.y1-1:s.y2-1);
            break;
        default:
            return 0;
    }
    if((s.m[x][0]==s.m[x][1]&&s.m[x][1]==s.m[x][2]&&s.m[x][2]==s.m[x][3]) ||
       (s.m[0][y]==s.m[1][y]&&s.m[1][y]==s.m[2][y]&&s.m[2][y]==s.m[3][y]) ||
       (s.m[0][0]==s.m[1][1]&&s.m[1][1]==s.m[2][2]&&s.m[2][2]==s.m[3][3]) ||
       (s.m[0][3]==s.m[1][2]&&s.m[1][2]==s.m[2][1]&&s.m[2][1]==s.m[3][0])  )
        return 1;
    return 0;
}
 
int main()
{
    readin();
    chu();
    st s, t;
    int n = 0; //迭代
    while(++n != 10000000)
    {
        s = q.front(); q.pop();
        if(check(s)) break;
        t = s;
        // 要判断是否这个点是从原来方向移动得到的,如果要向上移,则p域就不能是下面,否则会大大损耗空间和时间
        if(t.x1+1<4 && t.p1 != DOWN && t.m[t.x1+1][t.y1] != O && t.m[t.x1+1][t.y1]-1 == t.who) //第一个空格 向下移
        {
            t.p1 = UP; t.p2 = NUL;
            t.x1++; t.m[t.x1-1][t.y1] = t.m[t.x1][t.y1];
            t.m[t.x1][t.y1] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.x2+1<4 && t.p2 != DOWN && t.m[t.x2+1][t.y2] != O && t.m[t.x2+1][t.y2]-1 == t.who) //第二个空格 向下移
        {
            t.p2 = UP; t.p1 = NUL;
            t.x2++; t.m[t.x2-1][t.y2] = t.m[t.x2][t.y2];
            t.m[t.x2][t.y2] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.y1+1<4 && t.p1 != RIGHT && t.m[t.x1][t.y1+1] != O && t.m[t.x1][t.y1+1]-1 == t.who) //第一个空格 向右移
        {
            t.p1 = LEFT; t.p2 = NUL;
            t.y1++; t.m[t.x1][t.y1-1] = t.m[t.x1][t.y1];
            t.m[t.x1][t.y1] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.y2+1<4 && t.p2 != RIGHT && t.m[t.x2][t.y2+1] != O && t.m[t.x2][t.y2+1]-1 == t.who) //第二个空格 向右移
        {
            t.p2 = LEFT; t.p1 = NUL;
            t.y2++; t.m[t.x2][t.y2-1] = t.m[t.x2][t.y2];
            t.m[t.x2][t.y2] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.x1 > 0 && t.p1 != UP && t.m[t.x1-1][t.y1] != O && t.m[t.x1-1][t.y1]-1 == t.who) //第一个空格 向上移
        {
            t.p1 = DOWN; t.p2 = NUL;
            t.x1--; t.m[t.x1+1][t.y1] = t.m[t.x1][t.y1];
            t.m[t.x1][t.y1] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.x2 > 0 && t.p2 != UP && t.m[t.x2-1][t.y2] != O && t.m[t.x2-1][t.y2]-1 == t.who) //第二个空格 向上移
        {
            t.p2 = DOWN; t.p1 = NUL;
            t.x2--; t.m[t.x2+1][t.y2] = t.m[t.x2][t.y2];
            t.m[t.x2][t.y2] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.y1 > 0 && t.p1 != LEFT && t.m[t.x1][t.y1-1] != O && t.m[t.x1][t.y1-1]-1 == t.who) //第一个空格 向左移
        {
            t.p1 = RIGHT; t.p2 = NUL;
            t.y1--; t.m[t.x1][t.y1+1] = t.m[t.x1][t.y1];
            t.m[t.x1][t.y1] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
        t = s;
        if(t.y2 > 0 && t.p2 != LEFT && t.m[t.x2][t.y2-1] != O && t.m[t.x2][t.y2-1]-1 == t.who) //第二个空格 向左移
        {
            t.p2 = RIGHT; t.p1 = NUL;
            t.y2--; t.m[t.x2][t.y2+1] = t.m[t.x2][t.y2];
            t.m[t.x2][t.y2] = O; t.d++; t.who = !t.who;
            q.push(t);
        }
    }
 
    cout << s.d << endl;
    return 0;
}

*******************************2014-02-05*******************************

算法:BFS+Hash判重

裸BFS后,看了题解,有 Hash判重 知识,可算长姿势了。

Hash判重:将图看成一串数字,我们可以发现,这可以当作n进制的数看待,那么hash就有着落了。。我们将这个n进制数转换为十禁止,再开个数组,就可以hash了

这题的图元素只有3个,那么我们就可以将它看成3进制数来做hash。

注意:做hash的时候的mod要用质数(自己想为什么),因为这个图的长度为16,有7个2,那么经过粗略计算,这个hash的mod在40700000的后面,自己写了个小prime判定,找出了一个质数 40700017,就用它了。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <cstring>
using namespace std;
 
struct Map {
    int m[4][4], x1, x2, y1, y2;
    int ans, who;
    Map& operator= (Map& a) { memcpy(m, a.m, sizeof(a.m)); x1=a.x1; x2=a.x2; y1=a.y1; y2=a.y2; ans=a.ans; who=a.who; return *this; }
}q[600009]; //我们模拟队列,开那么多应该够了吧。。不够就用循环队列
Map t; //作为全局temp
 
const int mod = 40700017;
bool Hash[mod];
 
bool check(int f) {
    //判断行和列
    for(int i = 0; i < 4; ++i)
        if( (q[f].m[i][0]==q[f].m[i][1] && q[f].m[i][1]==q[f].m[i][2] && q[f].m[i][2]==q[f].m[i][3]) ||
            (q[f].m[0][i]==q[f].m[1][i] && q[f].m[1][i]==q[f].m[2][i] && q[f].m[2][i]==q[f].m[3][i]) )
            return true;
    //判断斜边
    if( (q[f].m[0][0]==q[f].m[1][1] && q[f].m[1][1]==q[f].m[2][2] && q[f].m[2][2]==q[f].m[3][3]) ||
        (q[f].m[0][3]==q[f].m[1][2] && q[f].m[1][2]==q[f].m[2][1] && q[f].m[2][1]==q[f].m[3][0]) )
        return true;
    return false;
}
 
void swap(int x, int y, int xx, int yy, int w) {
    t.m[x][y] = t.m[xx][yy];
    t.m[xx][yy] = 0;
    if(w == 1) t.x1 = xx, t.y1 = yy;
    else       t.x2 = xx, t.y2 = yy;
    t.who = t.m[x][y];
}
 
bool hash(Map& s) {
    //k是3^x次方的结果
    int i, j, k = 1, h = 0;
    for(i = 0; i < 4; ++i)
        for(j = 0; j < 4; ++j) {
            h += s.m[i][j] * k;
            k *= 3;
        }
    h %= mod;
    if(Hash[h]) return false;
    Hash[h] = 1;
    return true;
}
 
void bfs() {
    int f = 0, l = 1;
    int x1, y1, x2, y2;
    while(f != l) {
        if(check(f)) { cout << q[f].ans; break; }
        q[f].ans++;
        x1 = q[f].x1; y1 = q[f].y1; x2 = q[f].x2; y2 = q[f].y2;
        //8种情况。。我承认可以简略代码的,但是算了。这样看起来壮观 >_<
        if(x1 > 0 && q[f].m[x1-1][y1] != q[f].who) { t = q[f]; swap(x1, y1, x1-1, y1, 1); if(hash(t)) q[l++] = t; }
        if(x1 < 3 && q[f].m[x1+1][y1] != q[f].who) { t = q[f]; swap(x1, y1, x1+1, y1, 1); if(hash(t)) q[l++] = t; }
        if(y1 > 0 && q[f].m[x1][y1-1] != q[f].who) { t = q[f]; swap(x1, y1, x1, y1-1, 1); if(hash(t)) q[l++] = t; }
        if(y1 < 3 && q[f].m[x1][y1+1] != q[f].who) { t = q[f]; swap(x1, y1, x1, y1+1, 1); if(hash(t)) q[l++] = t; }
        if(x2 > 0 && q[f].m[x2-1][y2] != q[f].who) { t = q[f]; swap(x2, y2, x2-1, y2, 2); if(hash(t)) q[l++] = t; }
        if(x2 < 3 && q[f].m[x2+1][y2] != q[f].who) { t = q[f]; swap(x2, y2, x2+1, y2, 2); if(hash(t)) q[l++] = t; }
        if(y2 > 0 && q[f].m[x2][y2-1] != q[f].who) { t = q[f]; swap(x2, y2, x2, y2-1, 2); if(hash(t)) q[l++] = t; }
        if(y2 < 3 && q[f].m[x2][y2+1] != q[f].who) { t = q[f]; swap(x2, y2, x2, y2+1, 2); if(hash(t)) q[l++] = t; }
        f++;
    }
}
 
int main() {
    char t; bool ok = 1;
    for(int i = 0; i < 4; ++i) for(int j = 0; j < 4; ++j) {
        cin >> t;
        switch(t) {
        case 'B': q[0].m[i][j] = 2; break;
        case 'W': q[0].m[i][j] = 1; break;
        case 'O': q[0].m[i][j] = 0;
                  if(ok) q[0].x1 = i, q[0].y1 = j, ok = 0;
                  else   q[0].x2 = i, q[0].y2 = j;
                  break;
        }
    }
    bfs();
    return 0;
}

  

posted @   iwtwiioi  阅读(624)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· DeepSeek+PageAssist实现本地大模型联网
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· 从 14 秒到 1 秒:MySQL DDL 性能优化实战
点击右上角即可分享
微信分享提示