zoj1083 Frame Stacking 拓扑排序,Dfs

      若干个矩形框架覆盖在一起,给出叠在一起后的俯视图,求框架所有可能的摆放顺序(字典序递增),给出的数据中,保证每个框架的每条边上至少出现一个字符。

由于保证了每个框架每条边上至少有一个标记,那么可以求出每个框架的x,y的最大值和最小值,那么它的位置也就能确定了,之后直接Dfs一遍存下答案,排序输出就行。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
using namespace std;
typedef long long ll;
const int fx[4]={0,1,0,-1};
const int fy[4]={1,0,-1,0};

int idx(char c)
{
    if(c>='A' && c<='Z') return c-'A';
    else return c-'a'+26;
}
bool f[100];
char fdx[100];
int g[100][100];
int n,m,p,q;
int b[4][100];
char s[33][33];
int maxn;
bool slid(int x1,int y1,int x2,int y2,char c)
{
    for (int i=x1; i<=x2; i++)
    {
        if (s[i][y1]!='.' && s[i][y1]!=c) return false;
        if (s[i][y2]!='.' && s[i][y2]!=c) return false;
    }
    for (int j=y1; j<=y2; j++)
    {
        if (s[x1][j]!='.' && s[x1][j]!=c) return false;
        if (s[x2][j]!='.' && s[x2][j]!=c) return false;
    }
    return true;
}
void del(int x1,int y1,int x2,int y2)
{
    for (int i=x1; i<=x2; i++)
    {
        s[i][y1]=s[i][y1]='.';
        s[i][y2]=s[i][y2]='.';
    }
    for (int j=y1; j<=y2; j++)
    {
        s[x1][j]=s[x1][j]='.';
        s[x2][j]=s[x2][j]='.';
    }
}
string ss[20000];
vector<char> ans;
int cnt;
void print()
{
    for (int i=ans.size()-1; i>=0; i--)
    ss[cnt]+=ans[i];
    cnt++;
}
void dfs(int l)
{
    char ts[33][33];
    memcpy(ts,s,sizeof s);
    for (int i=0; i<52; i++)
    if (f[i])
    {
        if (slid(b[0][i],b[1][i],b[2][i],b[3][i],fdx[i]))
        {
            f[i]=false;
            del(b[0][i],b[1][i],b[2][i],b[3][i]);
            ans.push_back(fdx[i]);
            if (l==maxn) print();
            else dfs(l+1);
            f[i]=true;
            memcpy(s,ts,sizeof s);
            ans.pop_back();
        }
    }
}
int id,cd[100];
int main()
{
//    freopen("in.txt","r",stdin);
    for (char c='a'; c<='z'; c++)
    fdx[idx(c)]=c;
    for (char c='A'; c<='Z'; c++)
    fdx[idx(c)]=c;

    while(~scanf("%d",&n))
    {
        for (int i=0; i<20000; i++)
        ss[i]="";
        memset(f,false,sizeof f);
        memset(b[0],0x3f,sizeof b[0]);
        memset(b[1],0x3f,sizeof b[1]);
        memset(b[2],-1,sizeof b[2]);
        memset(b[3],-1,sizeof b[3]);
        scanf("%d",&m);
        for (int i=0; i<n; i++)
        {
            scanf("%s",s[i]);
        }
        maxn=0;
        for (int i=0; i<n; i++)
         for (int j=0; j<m; j++)
         {
             int id=idx(s[i][j]);
             f[id]=true;

             b[0][id]=min(b[0][id],i);
             b[1][id]=min(b[1][id],j);
             b[2][id]=max(b[2][id],i);
             b[3][id]=max(b[3][id],j);
         }

        for (int i=0; i<52; i++)
        if (f[i]) maxn++;
        cnt=0;
        dfs(1);
        sort(&ss[0],&ss[cnt]);
        for (int i=0; i<cnt; i++)
        cout<<ss[i]<<endl;
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值