連連看是一種很受大家歡迎的小游戲。下面四張圖給出了最基本的消除規(guī)則:

圖 A 中出現(xiàn)在同一直線上無障礙的圈圈可以消除;圖 B 中兩個圈圈可以通過一次轉(zhuǎn)彎消除;圖 C 和圖 D 中,兩個圈圈可以通過兩次轉(zhuǎn)彎消除。
首先需要判斷路上是否有障礙物
func isBlocked(full [][]byte,i,j int)bool {
if full[i][j]=='.'{
return false
}
return true
}
判斷是否是圖A的情況,則需要判斷水平或者豎直是否能直接聯(lián)通
/檢測水平之間是否聯(lián)通
func horizon(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
if x1!=x2{
return false
}
start := min(y1,y2)
end := max(y1,y2)
for j:=start+1;j<end;j++{
if isBlocked(full,x1,j){
return false
}
}
return true
}
//豎直是否聯(lián)通
func vertical(full [][]byte,x1,y1,x2,y2 int)bool{
if x1==x2&&y1==y2{
return false
}
if y1!=y2{
return false
}
start := min(x1,x2)
end := max(x1,x2)
for j:=start+1;j<end;j++{
if isBlocked(full,j,y1){
return false
}
}
return true
}
判斷圖B的情況,即如下圖所示

能A-C豎直+C-B水平
或者A-D水平,D-B豎直
//C B(x2,y2)
//A(x1,y1) D
//單個拐角之間是否能聯(lián)通
func sigTurn(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
c_x,c_y := x2,y1
d_x,d_y := x1,y2
var ret bool
if !isBlocked(full,c_x,c_y){
ret = ret||(horizon(full,x1, y1, c_x, c_y) && vertical(full,c_x, c_y, x2, y2))
}
if !isBlocked(full,d_x,d_y){
ret = ret||(horizon(full,x1, y1, d_x, d_y) && vertical(full,d_x, d_y, x2, y2))
}
return ret
}
判斷圖C和圖D的情況
兩個拐角檢測 = 一個拐角檢測 && (水平檢測 || 垂直檢測)

如圖,水平、垂直分別穿過 A B 共有四條直線,掃描直線上所有不包含 A B 的點(diǎn),看是否存在一點(diǎn) C ,滿足以下任意一項:
A 點(diǎn)至 C 點(diǎn)通過水平或垂直檢測,C 點(diǎn)至 B 點(diǎn)可通過一個拐角連接。(圖中用 C 表示)
A 點(diǎn)至 C 點(diǎn)可通過一個拐角連接,C 點(diǎn)至 B 點(diǎn)通過水平或垂直連接。(圖中用 C 下劃線表示)
//兩個拐角是否能聯(lián)通
//兩個拐角意思就是一個水品或者垂直到一個中間點(diǎn),又能拐角到另一個點(diǎn)
func twoTurn(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
l1 := len(full)
l2 := len(full[0])
for i:=0;i<l1;i++{
for j:=0;j<l2;j++{
if i!=x1&&i!=x2&&j!=y1&&j!=y2{//不在兩點(diǎn)的水平或者垂直線上
continue
}
if (i==x1&&j==y1)||(i==x2&&j==y2){
continue
}
if isBlocked(full,i,j){
continue
}
if sigTurn(full,x1,y1,i,j)&&(horizon(full,x1,y1,i,j)||vertical(full,x1,y1,i,j)){
return true
}
if sigTurn(full,i,j,x2,y2)&&(horizon(full,i,j,x2,y2)||vertical(full,i,j,x2,y2)){
return true
}
}
}
return false
}
附上完整代碼

package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var m,n int
fmt.Scanf("%d %d",&m,&n)
var qipan = make([][]byte,0)
bfio := bufio.NewReader(os.Stdin)
for i:=0;i<m;i++{
tmp,_:=bfio.ReadBytes('\n')
qipan = append(qipan,tmp)
}
fmt.Println(qipan)
var op int
fmt.Scanf("%d",&op)
for i:=0;i<op;i++{
var x1,y1,x2,y2 int
fmt.Scanf("%d %d %d %d",&x1,&y1,&x2,&y2)
if qipan[x1-1][y1-1]==qipan[x2-1][y2-1]&&remove(qipan,x1-1,y1-1,x2-1,y2-1){
fmt.Println("YES")
}else {
fmt.Println("NO")
}
}
}
func remove(full [][]byte,x1,y1,x2,y2 int)bool{
var ret bool
ret = horizon(full,x1,y1,x2,y2)
if ret{
full[x1][y1],full[x2][y2] = '.','.'
return true
}
ret = vertical(full,x1,y1,x2,y2)
if ret{
full[x1][y1],full[x2][y2] = '.','.'
return true
}
ret = sigTurn(full,x1,y1,x2,y2)
if ret{
full[x1][y1],full[x2][y2] = '.','.'
return true
}
ret = twoTurn(full,x1,y1,x2,y2)
if ret{
full[x1][y1],full[x2][y2] = '.','.'
return true
}
return false
}
func isBlocked(full [][]byte,i,j int)bool {
if full[i][j]=='.'{
return false
}
return true
}
//檢測水平之間是否聯(lián)通
func horizon(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
if x1!=x2{
return false
}
start := min(y1,y2)
end := max(y1,y2)
for j:=start+1;j<end;j++{
if isBlocked(full,x1,j){
return false
}
}
return true
}
//豎直是否聯(lián)通
func vertical(full [][]byte,x1,y1,x2,y2 int)bool{
if x1==x2&&y1==y2{
return false
}
if y1!=y2{
return false
}
start := min(x1,x2)
end := max(x1,x2)
for j:=start+1;j<end;j++{
if isBlocked(full,j,y1){
return false
}
}
return true
}
//C B(x2,y2)
//A(x1,y1) D
//單個拐角之間是否能聯(lián)通
func sigTurn(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
c_x,c_y := x2,y1
d_x,d_y := x1,y2
var ret bool
if !isBlocked(full,c_x,c_y){
ret = ret||(horizon(full,x1, y1, c_x, c_y) && vertical(full,c_x, c_y, x2, y2))
}
if !isBlocked(full,d_x,d_y){
ret = ret||(horizon(full,x1, y1, d_x, d_y) && vertical(full,d_x, d_y, x2, y2))
}
return ret
}
//兩個拐角是否能聯(lián)通
//兩個拐角意思就是一個水品或者垂直到一個中間點(diǎn),又能拐角到另一個點(diǎn)
func twoTurn(full [][]byte,x1,y1,x2,y2 int)bool {
if x1==x2&&y1==y2{
return false
}
l1 := len(full)
l2 := len(full[0])
for i:=0;i<l1;i++{
for j:=0;j<l2;j++{
if i!=x1&&i!=x2&&j!=y1&&j!=y2{//不在兩點(diǎn)的水平或者垂直線上
continue
}
if (i==x1&&j==y1)||(i==x2&&j==y2){
continue
}
if isBlocked(full,i,j){
continue
}
if sigTurn(full,x1,y1,i,j)&&(horizon(full,x1,y1,i,j)||vertical(full,x1,y1,i,j)){
return true
}
if sigTurn(full,i,j,x2,y2)&&(horizon(full,i,j,x2,y2)||vertical(full,i,j,x2,y2)){
return true
}
}
}
return false
}
func max(i,j int)int {
if i > j{
return i
}
return j
}
func min(i,j int)int {
if i < j{
return i
}
return j
}