zoukankan      html  css  js  c++  java
  • p1228

    这是一道图论呦.

    这怎么和图论相关呢?差分约束不是也看起来和图论无关么2333.

    那么本题就类似于差分约束.考虑到矩形的每一条边都有一部分露出来,那么可以m*n的用至少四个点更新每个字母的四个顶角位置.然后对于每个有顶角的字母跑它的四个边,如果有别的字母就说明这个字母再本字母之上,连一条有向边.(在这里连的话很大几率使两点间有多个边.考虑到点最多有26个,可以写一个邻接矩阵)

    这样就有了一个有向无环图,我们要做的就是按照字典序输出所有可行顺序.这个怎么弄呢?如果只输出一个的话我会维护堆后拓扑排序全部输出的话...依旧欺负它点少,我们直接上一个带dfs的回溯拓扑就好.

    我写的还是个邻接表...并且记录入度和是否有点flag.对于从'a'到'z'如果flag==1且入度为0就记录答案,flag改为1,然后dfs冲进去,对于从a到z再判断一下,记录答案,所连边sum--,然后再冲进去.如果dfs层数为n时输出return,并打扫现场.

    为什么这样子能做到字典序从小到大呢?因为每次把字母放进ans时是从A到Z的.而邻接表的遍历对然是逆字典序的,但是不影响答案啊.

    46 .
    65 A
    90 Z

    虽然字符和数字间可以这样转化,但是实际上并不需要这么严格,字符实际上就是数字.

    using namespace std;
    int i,f,t;
    char ch;
    char ans[100];
    int n,m;
    int l[100],r[100],u[100],d[100],sum[100],flag[100],a[100][100],o[100][100];
    struct node{
        int x,y,next;
    }e[10000];
    int tot,head[100];
    void add(int x,int y){
        tot++;
        e[tot].x=x;
        e[tot].y=y;
        e[tot].next=head[x];
        head[x]=tot;
    }
    void dfs(int now)
    {
        if(now==n){
            for(int j=1;j<=n;j++)
                cout<<ans[j];
            cout<<endl;
            return;
        }
        now++;
        for(int k=65;k<=90;k++)
            if(!sum[k]&&flag[k]){
                for(int j=head[k];j!=0;j=e[j].next)
                    sum[e[j].y]--;
                ans[now]=k;
                flag[k]=0;//改一下
                dfs(now);
                flag[k]=1;//打扫现场
                for(int j=head[k];j!=0;j=e[j].next)
                    sum[e[j].y]++;
            }
    }    
    int main()
    {
        cin>>n>>m;
        memset(l,127,sizeof(l));
        memset(u,127,sizeof(u));
        for(i=1;i<=n;i++)
            for(f=1;f<=m;f++){
                cin>>ch;
                a[i][f]=t=int(ch);
                l[t]=min(f,l[t]);
                r[t]=max(f,r[t]);
                u[t]=min(i,u[t]);
                d[t]=max(i,d[t]);
            }
        for(t=65;t<=90;t++){
            if(r[t]!=0){
                
                f=l[t];
                for(i=u[t];i<=d[t];i++)
                    if(a[i][f]!=t)
                        o[t][a[i][f]]=1;
                f=r[t];
                for(i=u[t];i<=d[t];i++)
                    if(a[i][f]!=t)
                        o[t][a[i][f]]=1;
                i--;
                for(f=l[t];f<=r[t];f++)
                    if(a[i][f]!=t)
                        o[t][a[i][f]]=1;
                i=u[t];
                for(f=l[t];f<=r[t];f++)
                    if(a[i][f]!=t)
                        o[t][a[i][f]]=1;
                flag[t]=1;
            }
        }
        n=0;
        for(i=65;i<=90;i++){
            for(f=65;f<=90;f++)
                if(o[i][f])
                    sum[f]++,add(i,f);//连边,统计入度
            if(flag[i])//统计总点数n
                n++;
        }
        for(i=65;i<=90;i++){
            if(!sum[i]&&flag[i]){
                for(int j=head[i];j!=0;j=e[j].next)
                    sum[e[j].y]--;
                ans[1]=i;
                flag[i]=0;
                dfs(1);//来啊快活啊
                flag[i]=1;//打扫现场
                for(int j=head[i];j!=0;j=e[j].next)
                    sum[e[j].y]++;
            }
        }
        return 0;
    }

    我可能永远也习惯不了这样子的缩进,但还是要努力学习.

    让我去吐一会...

  • 相关阅读:
    Html5实现iPhone开机界面
    Html5游戏开发-145行代码完成一个RPG小Demo
    HTML5开源RPG游戏引擎lufylegendRPG 1.0.0发布
    如何制作一款HTML5 RPG游戏引擎——第五篇,人物&人物特效
    如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话
    如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景
    html5游戏开发-零基础开发《圣诞老人送礼物》小游戏
    如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果
    如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现
    读CopyOnWriteArrayList有感
  • 原文地址:https://www.cnblogs.com/qywyt/p/9690046.html
Copyright © 2011-2022 走看看