#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
struct Node
{
int x, y, se, d, c;
};
queue < Node > Q;
int move[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int vis[11][11], mat[11][11], card[4], flag, N, M;
char Map[11][11];
inline int off(int x, int y, int c)
{
if (!(x >= 0 && x < N && y >= 0 && y < M)) return 0;
if (mat[x][y] != -1 && mat[x][y] != c) return 0;
return 1;
}
inline int isAB(int a, int b)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
if (mat[i][j] == a)
{
if (mat[i + 1][j + 1] == a && mat[i][j + 1] == b && mat[i + 1][j] == b) return 1;
else return 0;
}
if (mat[i][j] == b)
{
if (mat[i + 1][j + 1] == b && mat[i][j + 1] == a && mat[i + 1][j] == a) return 1;
else return 0;
}
}
}
}
inline int cut(void)
{
for (int i = 0; i < 4; i ++ )
{
for (int j = i + 1; j < 4; j ++ )
{
if (card[i] == card[j] && card[i] == 2)
{
if (isAB(i, j)) return 1;
else return 0;
}
}
}
}
int dfs(int count)
{
if (!count) return flag = 1;
if (cut()) return 0;
for (int i = 0; i < N; i ++ )
for (int j = 0; j < M; j ++ )
{
if (flag) return 1;
if (mat[i][j] != -1)
{
int c = mat[i][j];
int pos[10][2], cnt = 0;
memset(vis, 0, sizeof(vis));
Node nt, nt1;
nt.x = i;
nt.y = j;
nt.c = -1;nt.se = 0;
nt.d = -1;
vis[i][j] = 1;
Q.push(nt);
while(!Q.empty())
{
nt = Q.front();Q.pop();
if (nt.c == c)
{
pos[cnt][0] = nt.x;
pos[cnt][1] = nt.y;
cnt ++ ; continue;
}
for (int k = 0; k < 4; k ++ )
{
int x = nt.x + move[k][0], y = nt.y + move[k][1];
if (off(x, y, c) && !vis[x][y])
{
if (nt.d == k || nt.d == -1) nt1.se = nt.se;
else nt1.se = nt.se + 1;
if (nt1.se <= 2)
{
nt1.x = x;
nt1.y = y;
nt1.c = mat[x][y];
nt1.d = k;
vis[x][y] = 1;
Q.push(nt1);
}
}
}
}
mat[i][j] = -1;
card[c] -= 2;
for (int k = 0; k < cnt; k ++ )
{
if (flag) return 1;
int x = pos[k][0], y = pos[k][1];
mat[x][y] = -1;
dfs(count - 2);
mat[x][y] = c;
}
mat[i][j] = c;
card[c] += 2;
}
}
return 0;
}
int main(void)
{
// freopen("test.txt", "r", stdin);
while (scanf("%d%d", &N, &M) && N && M)
{
memset(card, 0, sizeof(card));
memset(mat, -1, sizeof(mat));
int count = 0; flag = 1;
for (int i = 0; i < N; i++ ) scanf("%s", Map[i]);
{
for (int i = 0;i < N;i ++ )
{
for (int j = 0;j < M;j ++ )
{
if (Map[i][j] == 'A') { card[0] ++ ;mat[i][j] = 0;}
else if (Map[i][j] == 'B') { card[1] ++ ;mat[i][j] = 1;}
else if (Map[i][j] == 'C') { card[2] ++ ;mat[i][j] = 2;}
else if (Map[i][j] == 'D') { card[3] ++ ;mat[i][j] = 3;}
else mat[i][j] = -1;
}
for (int i = 0;i < 4;i ++ )
{
count += card[i];
if (card[i]%2) flag = 0;
}
if (!flag) printf("no\n");
else
{
flag = 0;
dfs(count);
if (flag) printf("yes\n");
else printf("no\n");
}
}
}
}
return 0;
}
1.設直線的方程ax+bx+c=0(a>0);若點(x0,y0)代入方程:
若ax0+by0+c<0,則點在直線的左側;
若ax0+by0+c=0,則點在直線上;
若ax0+by0+c<0,則點在直線的右側;
但是前提是a>0,否則結果左右對調(WA了一次).
2.(x1,y1)和(x2,y2)爲某直線的兩個點,直線的方程就可以表示爲(y2-y1)(x-x1)-(x2-x1)(y-y1)=0;因爲n較大,而直線與直線對點具有序的關係,即點如果在某條直線的左側,那麼肯定在那條直線右側所有的直線的左側,
所以可用二分搜索把時間複雜度降爲O(nlogn);