USACO4.4 重叠的图像 Frame Up

题目链接

Solution

今天上午测试题...最后几分钟才看到要输出所有解,于是爆成了 44pts...

根据输入可以得到所有字母构成的矩形。如果字符 \(i\) 出现在了字符 \(j\) 的矩形上,那么 \(i\) 的图像一定在 \(j\) 的图像上方,从 \(j\)\(i\) 连边。

跑一个拓扑排序,每次可以选的是队列里所有点之一。因此需要 dfs 所有可能情况,最后存到变量里按照字典序输出。

手写队列要注意,不能直接对队列排序,dfs 时会造成混乱。

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 2333;
char a[N][N];
int n, m, Num = 0, tot = 0, res = 0;
int vis[N], lx[N], rx[N], ly[N], ry[N], e[N][N];
int q[N], du[N], use[N];
string ans[2333333];

void dfs(int num, int stp)
{
    if(stp == Num)
    {
        res++;
        ans[res] = "";
        for(int i = 1; i <= stp; i++) ans[res] += (char)(use[i]);
        return ;
    }
    for(int i = 1; i <= num; i++)
    {
        int x = q[i], cnt = num - 1;
        for(int j = i; j < num; j++) q[j] = q[j + 1];
        for(int j = 'A'; j <= 'Z'; j++)
        {
            if(vis[j] && e[x][j])
            {
                du[j]--;
                if(du[j] == 0) q[++cnt] = j;
            }
        }
        use[stp + 1] = x;
        dfs(cnt, stp + 1);
        for(int j = num; j > i; j--) q[j] = q[j - 1];
        q[i] = x;
        for(int j = 'A'; j <= 'Z'; j++)
            if(vis[j] && e[x][j]) du[j]++;
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    memset(e, 0, sizeof(e));
    memset(lx, 0x3f, sizeof(lx));
    memset(ly, 0x3f, sizeof(ly));
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            if(a[i][j] >= 'A' && a[i][j] <= 'Z')
            {
                if(!vis[a[i][j]])
                {
                    vis[a[i][j]] = 1;
                    Num++;
                }
                lx[a[i][j]] = min(lx[a[i][j]], i);
                ly[a[i][j]] = min(ly[a[i][j]], j);
                rx[a[i][j]] = max(rx[a[i][j]], i);
                ry[a[i][j]] = max(ry[a[i][j]], j);
            }
        }
    for(int i = 'A'; i <= 'Z'; i++)
    {
        if(!vis[i]) continue;
        for(int j = ly[i]; j <= ry[i]; j++)
        {
            char ch1 = a[lx[i]][j], ch2 = a[rx[i]][j];
            if(vis[ch1] && ch1 != i) e[i][ch1] = 1;
            if(vis[ch2] && ch2 != i) e[i][ch2] = 1;
        }
        for(int j = lx[i]; j <= rx[i]; j++)
        {
            char ch1 = a[j][ly[i]], ch2 = a[j][ry[i]];
            if(vis[ch1] && ch1 != i) e[i][ch1] = 1;
            if(vis[ch2] && ch2 != i) e[i][ch2] = 1;
        }
    }
    memset(du, 0, sizeof(du));
    for(int i = 'A'; i <= 'Z'; i++)
    {
        if(!vis[i]) continue;
        for(int j = 'A'; j <= 'Z'; j++)
        {
            if(!vis[j]) continue;
            if(e[i][j] == 1) du[j]++;
        }
    }
    for(int i = 'A'; i <= 'Z'; i++)
    {
        if(!vis[i]) continue;
        if(du[i] == 0)
        {
            tot++;
            q[tot] = i;
        }
    }
    dfs(tot, 0);
    sort(ans + 1, ans + res + 1);
    for(int i = 1; i <= res; i++) cout << ans[i] << endl;
    return 0;
}
posted @ 2020-11-29 15:48  Nyxia  阅读(121)  评论(0编辑  收藏  举报