POJ 1128

这倒题有一个非常坑爹的地方。。。。就是不止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;
}


还有自我检讨一下,写了这么旧的代码没有一点摸版意识,比如构图什么的应该单独拿出来写成一个函数,还有原谅我是一个新手,没有用空格的习惯,还有代码写的确实优点丑。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值