USACO 3.2.5 Magic Squares 魔板 msquare

USACO Add comments588 views


这道题类似于八数码难题,基本思想是宽搜,使用Hash判重。如果使用一般的八维数组空间可以达到8^8=16777216,会超过USACO的16MB空间限制。所以我们应该对状态进行散列存储,观察发现每位的数字不能重复,存在空间冗余。我们可以对于每个状态建立一个映射,采用康托展开算法。(参见Nocow)
定义cantor(s)为s串大大小顺序。可样将哈希容量缩减到8!=40320。

另外发现,对于魔板当前状态可以由一个8位的8进制数来表示,即无符号32位长整型 unsigned long 表示。
对于魔板的变换可以转化为对一个数字的位运算。这样可以大大提高程序效率。

程序有些长,但是效率很高。

USER: CmYkRgB CmYkRgB [cmykrgb1]
TASK: msquare
LANG: C++

Compiling…
Compile: OK

Executing…
Test 1: TEST OK [0.011 secs, 3476 KB]
Test 2: TEST OK [0.054 secs, 3444 KB]
Test 3: TEST OK [0.011 secs, 3476 KB]
Test 4: TEST OK [0.011 secs, 3472 KB]
Test 5: TEST OK [0.011 secs, 3480 KB]
Test 6: TEST OK [0.022 secs, 3476 KB]
Test 7: TEST OK [0.022 secs, 3476 KB]
Test 8: TEST OK [0.023 secs, 3484 KB]

All tests OK.

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
/*
ID: cmykrgb1
PROG: msquare
LANG: C++
*/
#include <iostream>
#include <fstream>
#define MAX 40320
using namespace std;
 
class state
{
public:
	state()
	{
		comefrom=0;cur=0;cont=0;
	}
	state *comefrom;
	unsigned long cur;
	short cont;
};
state O;
state S[MAX];
 
class queue
{
private:
	long first,last;
	long list[MAX];
public:
	long size;
 
	queue()
	{
		reset();
	}
 
	void reset()
	{
		first=0;
		size=0;
		last=-1;
	}
 
	void ins(state *comefrom,unsigned long cur,long cont)
	{
		size++;
		last++;
		list[last]=last;
		S[last].comefrom=comefrom;
		S[last].cur=cur;
		S[last].cont=cont;
	}
 
	long del()
	{
		size--;
		return list[first++];
	}
};
 
ifstream fi("msquare.in");
ofstream fo("msquare.out");
bool hash[MAX];
char B[4]={0,'A','B','C'};
 
long fac[8]={1,1,2,6,24,120,720,5040};
unsigned long Finish;
 
unsigned long cantor(unsigned long S)
{
	long x=0,i,p,k,j;
	bool hash[8]={false};
	for (i=8;i>=2;i--)
	{
		k=S>> 3*(i-1);
		S-=k<<3*(i-1);
		hash[k]=true;
		p=k;
		for (j=0;j<=k-1;j++)
			if (hash[j])
				p--;
		x+=fac[i-1]*p;
	}
	return x;
}
 
void init()
{
	long i,t;
	for (i=0;i<8;i++)
	{
		fi>>t;
		t--;
		O.cur*=8;
		O.cur+=t;
	}
	Finish=cantor(O.cur);
	hash[0]=true;
}
 
unsigned long turn(unsigned long S,int f)
{
	long i;
	unsigned long P=0;
	switch (f)
	{
	case 1:
		for (i=1;i<=8;i++)
			P+=(S & (7<< ( (i-1)*3) ) )>> (i-1)*3 << ((8-i)*3);
		return P;
		break;
	case 2:
		P+=(S & 07000)>>3*3;
		P+=(S & 00777)<<3;
		P+=(S & 070000)<<3*3;
		P+=(S & 077700000)>>3;
		return P;
		break;
	case 3:
		P= (S & 070077007);
		P+=(S & 070)<<5*3;
		P+=(S & 0700)>>1*3;
		P+=(S & 0700000)>>3*3;
		P+=(S & 07000000)>>1*3;
		return P;
		break;
	}
}
 
void print(long ed,long f)
{
	string O;
	state *P=&S[ed];
	char OUT[MAX];
	long cnt=0,i;
	while (P->cont)
	{
		cnt++;
		OUT[cnt]=B[P->cont];
		P=P->comefrom;
	}
 
	fo << cnt+1<<endl;
	for (i=cnt;i>=1;i--)
		fo << OUT[i];
	fo << B[f] << endl;
 
	fi.close();
	fo.close();
	exit(0);
}
 
void bfs()
{
	long i=0,j;
	queue Q;
	Q.ins(&O,001234567,0);
	while (Q.size)
	{
		unsigned long p,ct;
		i=Q.del();
		for (j=1;j<=3;j++)
		{
			p=turn(S[i].cur,j);
			ct=cantor(p);
			if (!hash[ct])
			{
				hash[ct]=true;
				if (ct==Finish)
					print(i,j);
				Q.ins(&S[i],p,j);
			}
		}
	}
}
 
int main()
{
	init();
	bfs();
	fo << '0' <<'n'<<'n';
	fi.close();
	fo.close();
	return 0;
}

相關日誌

标签:, , ,


3 Responses to “USACO 3.2.5 Magic Squares 魔板 msquare”

  1. Neil Says:

    家宝兄, 这个代码很强,
    OI很少有人用类,
    就是这个ins功能写得不是很规范: S 不该属于queue类,不在同一层抽象
    void ins(state *comefrom,unsigned long cur,long cont)
    {
    size++;
    last++;
    list[last]=last;
    S[last].comefrom=comefrom;
    S[last].cur=cur;
    S[last].cont=cont;
    }

    [回复]

  2. CmYkRgB123 Says:

    嗯,的确不够规范,我都把S数组定义在类上面了。图方便,懒省事。

    谢谢这位仁兄的提议

    [回复]

  3. 1015380720 Says:

    I can’t follow you.

    [回复]

Leave a Reply

40 queries. 0.502 seconds. Designed by NattyWP .
Images by desEXign.