第一道双向广搜,188MS
题意:给定一个4X4的“+”“-”图,定义操作[i,j]为改变第i行和第j列的状态,输出使原图变为全“-”图的最小的操作数和各具体操作
#include
<
iostream
>
using
namespace
std;
#define
MAXN 2<<17
int
r[
5
]
=
{
0
,
61440
,
3840
,
240
,
15
};
int
c[
5
]
=
{
0
,
34952
,
17476
,
8738
,
4369
};
int
rc[
5
][
5
]
=
{
{
0
,
0
,
0
,
0
,
0
},
{
0
,
32768
,
16384
,
8192
,
4096
},
{
0
,
2048
,
1024
,
512
,
256
},
{
0
,
128
,
64
,
32
,
16
},
{
0
,
8
,
4
,
2
,
1
}
};
int
open[MAXN],head,tail,mk[MAXN],st,ed,opera[MAXN],pre[MAXN],ans[MAXN],cnt;
char
ss[
6
][
6
];
int
change(
int
i,
int
j,
int
s){
int
ns;
ns
=~
(r[i]
^
(
~
s));
ns
=~
(c[j]
^
(
~
ns));
ns
=~
(rc[i][j]
^
(
~
ns));
return
ns;
}
void
output(
int
s,
int
ns){
if
(mk[s]
==
2
){
int
t
=
s;
s
=
ns;
ns
=
t;
}
while
(s
!=
st){
ans[cnt
++
]
=
opera[s];
s
=
pre[s];
};
while
(ns
!=
ed){
ans[cnt
++
]
=
opera[ns];
ns
=
pre[ns];
};
}
void
solve(){
int
i,j,s,ns;
if
(st
==
ed){
printf(
"
0\n
"
);
return
;
}
open[
0
]
=
st;
open[
1
]
=
ed;
mk[st]
=
1
;
mk[ed]
=
2
;
head
=
0
;
tail
=
2
;
while
(head
<
tail){
s
=
open[head
++
];
for
(i
=
1
;i
<=
4
;i
++
){
for
(j
=
1
;j
<=
4
;j
++
){
ns
=
change(i,j,s);
if
(
!
mk[ns]){
mk[ns]
=
mk[s];
opera[ns]
=
i
*
10
+
j;
pre[ns]
=
s;
open[tail
++
]
=
ns;
}
else
{
if
(mk[s]
!=
mk[ns]){
//
cout<<"!!\n";
//
printf("%d %d\n",i,j);
ans[cnt
++
]
=
i
*
10
+
j;
output(s,ns);
return
;
}
}
}
}
}
return
;
}
int
main(){
cnt
=
0
;
int
i,j,k;
for
(i
=
0
;i
<
4
;i
++
)
gets(ss[i]);
st
=
ed
=
0
;
k
=
0
;
//
建立st的位图
for
(i
=
3
;i
>=
0
;i
--
){
for
(j
=
3
;j
>=
0
;j
--
){
if
(ss[i][j]
==
'
+
'
)
st
+=
1
<<
k;
k
++
;
}
}
solve();
printf(
"
%d\n
"
,cnt);
for
(i
=
0
;i
<
cnt;i
++
)
printf(
"
%d %d\n
"
,ans[i]
/
10
,ans[i]
%
10
);
return
0
;
}