昨天做题突然想起来的一道题.
08年亚洲赛北京区一道简单题,一道枚举题.
大体题意:
由字母组成的框体(FRAME),相互覆盖,求最上面一个,有一些需要注意的地方:
1.有可能出现有一条边被盖上的情况.
2.有可能出现被包裹的情况了.
解题思路:
1.枚举每一个点,求每一个字母边框的左上角和右下角位置和字母出现的个数.
2.纪录完毕后,枚举检测每一个字母,根据纪录的坐标求出应有的字母个数和纪录的字母数对比若相同进入下一步,否则舍弃.
3.因为可能出现包含的情况,确定一个没被覆盖的字母框后,要检测其包含的区域中是否有一个完整的边框.
判定方法为,检测到一个未检查过的字符时,调出其纪录,对比其横纵坐标.
源代码:
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <list>
#include <climits>
#include <ctime>
#include <functional>
#include <iterator>
using namespace std;
const int N=110;
const int ASCII=26;
typedef struct _point
{
public :
int x1,y1;
int x2,y2;
int num;
void init() {
x1=y1=200;
x2=y2=num=0;
}
void setPoint(int x,int y) {
x1=min(x1,x);
y1=min(y1,y);
x2=max(x2,x);
y2=max(y2,y);
num++;
}
}Point;
int n,m;
char a[N][N];
Point point[ASCII];
inline void init()
{
for(int i=0;i<n;++i)
scanf("%s",a[i]);
for(int i=0;i<ASCII;++i)
point[i].init();
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
if(a[i][j]!='.')
point[a[i][j]-'A'].setPoint(i,j);
}
inline bool rec(const Point &ta,const Point &tb)
{
if(ta.x1>tb.x1||ta.y1>tb.y1)
return false;
if(ta.x2<tb.x2||ta.y2<tb.y2)
return false;
return true;
}
inline bool isOk(const Point &tp)
{
bool _hash[ASCII];
memset(_hash,false,sizeof(_hash));
for(int i=tp.x1+1;i<tp.x2;++i) {
for(int j=tp.y1+1;j<tp.y2;++j) {
if(!_hash[a[i][j]-'A']&&a[i][j]!='.') {
_hash[a[i][j]-'A']=true;
if(rec(tp,point[a[i][j]-'A']))
return false;
}
}
}
return true;
}
inline void work()
{
for(int i=0;i<ASCII;++i) {
int t=(point[i].x2-point[i].x1+point[i].y2-point[i].y1)*2;
if(point[i].num&&t==point[i].num)
if(isOk(point[i]))
printf("%c",i+'A');
}
puts("");
}
int main()
{
while(~scanf("%d%d",&n,&m),n) {
init();
work();
}
return 0;
}