这倒题有一个非常坑爹的地方。。。。就是不止5张牌。。可以是1张也可以是26张。。。。
剩下的就是构图+DFS 个人感觉重点在构图,用四个数组记录下每一个字母的最大最小行和列。然后枚举4条边就好。
还有,输出有可能有多组,所谓的按字典序输出和POJ 1270一样,这道题目还不用排序,比1270还要简单一些,不过在强调一次用做记录答案的ans数组一定要记得初始化,这个点我吃了不少亏。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 1000000
using namespace std;
int xmin[550],xmax[550],ymin[550],ymax[550],sum[100];//数组开大点,不然很容易RE。。我开这么大是偷懒了,没仔细计算上限。
char map[105][105];
int charge[105][105],ccc[55];
int judge[55];
char ans[10];
int n,m,num;
void dfs(int k){
if(k==num){
printf("%s\n",ans);
return;
}
for(int i=0;i<=26;i++){
//if(ccc[i]==0) continue;
if(sum[i]==0&&judge[i]==0&&ccc[i]==1){
judge[i]=1;
for(int j=0;j<=26;j++){//拓扑排序
if(charge[i][j]==1) sum[j]--;
}
ans[k]=i+'A';
dfs(k+1);
judge[i]=0;
for(int j=0;j<=26;j++){//还原
if(charge[i][j]==1) sum[j]++;
}
}
}
return;
}
int main(){
while(scanf("%d",&n)!=EOF){
scanf("%d",&m);
//printf("%d %d",n,m);
//for(int i=0;i<n;i++) printf("%s\n",map[i]);
memset(ans,0,sizeof(ans));
memset(judge,0,sizeof(judge));
memset(map,0,sizeof(map));
memset(xmax,-1,sizeof(xmax));
memset(ymax,-1,sizeof(ymax));
memset(charge,0,sizeof(charge));//记录两点之间是否有边。
memset(ccc,0,sizeof(ccc));//记录有出现的是那些牌
memset(sum,0,sizeof(sum));//记录每个点的入度数
for(int i=0;i<n;i++) scanf("%s",map[i]);
for(int i=0;i<=26;i++){
ymin[i]=INF;
xmin[i]=INF;
}
//初始化。这一点非常重要,这里每做好很容易WA
//printf("yes\n");
num=0;//记录牌的种数;
//构图
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(map[i][j]=='.') continue;
int t=map[i][j]-'A';
if(ccc[t]==0){
ccc[t]=1;
num++;
}
//printf("%d\n",t);
if(xmax[t] < i) xmax[t]=i;
if(ymax[t] < j) ymax[t]=j;
if(xmin[t] > i) xmin[t]=i;
if(ymin[t] > j) ymin[t]=j;
}
}
//printf("%d\n",num);
//for(int i=0;i<5;i++) printf("%d %d %d %d\n",xmin[i],ymin[i],xmax[i],ymax[i]);
for(int i=0;i<=26;i++){
if(ccc[i]==0) continue;
int x,y;
x=xmin[i];
for(y=ymin[i];y<=ymax[i];y++){
if((map[x][y]-'A')!=i&&charge[i][map[x][y]-'A']==0){
charge[i][map[x][y]-'A']=1;
sum[map[x][y]-'A']++;
}
}
x=xmax[i];
for(y=ymin[i];y<=ymax[i];y++){
if((map[x][y]-'A')!=i&&charge[i][map[x][y]-'A']==0){
charge[i][map[x][y]-'A']=1;
sum[map[x][y]-'A']++;
}
}
y=ymin[i];
for(x=xmin[i];x<=xmax[i];x++){
if((map[x][y]-'A')!=i&&charge[i][map[x][y]-'A']==0){
charge[i][map[x][y]-'A']=1;
sum[map[x][y]-'A']++;
}
}
y=ymax[i];
for(x=xmin[i];x<=xmax[i];x++){
if((map[x][y]-'A')!=i&&charge[i][map[x][y]-'A']==0){
charge[i][map[x][y]-'A']=1;
sum[map[x][y]-'A']++;
}
}
}
//for(int i=0;i<4;i++) printf("%d\n",sum[i]);
dfs(0);
}
return 0;
}
还有自我检讨一下,写了这么旧的代码没有一点摸版意识,比如构图什么的应该单独拿出来写成一个函数,还有原谅我是一个新手,没有用空格的习惯,还有代码写的确实优点丑。