DFS Gym100827K Towers

传送门:点击打开链接

题意:类似数独,不过还有另外一种限制,从左往右看,从右往左看,从上往下看,从下往上看,看到的塔数应该是固定的。

思路:暴搜。好久没暴搜了,呼呼。。

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;

const int MX = 1e2 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

char s[MX][MX];
int vis[2][MX][MX], r, n;
struct Point {
    int x, y;
} P[MX];

bool left(int i, int tot) {
    int ret = 0, now = 0, cnt = 0;
    for(int j = 1; j <= n; j++) {
        if(s[i][j] > now) now = s[i][j], ret++;
        if(s[i][j]) cnt++;
    }
    if(cnt == n) return ret == tot;
    return ret <= tot;
}
bool right(int i, int tot) {
    int ret = 0, now = 0, cnt = 0;
    for(int j = n; j >= 1; j--) {
        if(s[i][j] > now) now = s[i][j], ret++;
        if(s[i][j]) cnt++;
    }
    if(cnt == n) return ret == tot;
    return true;
}
bool top(int j, int tot) {
    int ret = 0, now = 0, cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(s[i][j] > now) now = s[i][j], ret++;
        if(s[i][j]) cnt++;
    }
    if(cnt == n) return ret == tot;
    return ret <= tot;
}
bool foot(int j, int tot) {
    int ret = 0, now = 0, cnt = 0;
    for(int i = n; i >= 1; i--) {
        if(s[i][j] > now) now = s[i][j], ret++;
        if(s[i][j]) cnt++;
    }
    if(cnt == n) return ret == tot;
    return true;
}
bool check(int i, int j, int t) {
    if(vis[0][i][t]) return false;
    if(vis[1][j][t]) return false;
    s[i][j] = t;
    if(s[i][0] && !left(i, s[i][0])) return s[i][j] = 0;
    if(s[i][n + 1] && !right(i, s[i][n + 1])) return s[i][j] = 0;
    if(s[0][j] && !top(j, s[0][j])) return s[i][j] = 0;
    if(s[n + 1][j] && !foot(j, s[n + 1][j])) return s[i][j] = 0;
    vis[0][i][t] = vis[1][j][t] = 1;
    return true;
}
bool check_all() {
    for(int i = 0; i <= n + 1; i++) {
        for(int j = 0; j <= n + 1; j++) {
            s[i][j] = isdigit(s[i][j]) ? s[i][j] - '0' : 0;
            if(1 <= i && i <= n && 1 <= j && j <= n) {
                int t = s[i][j];
                if(t) {
                    if(vis[0][i][t]) return false;
                    if(vis[1][j][t]) return false;
                    vis[0][i][t] = vis[1][j][t] = 1;
                } else P[r].x = i, P[r].y = j, r++;
            }
        }
    }
    for(int i = 1; i <= n; i++) {
        if(s[i][0] && !left(i, s[i][0])) return false;
        if(s[i][n + 1] && !right(i, s[i][n + 1])) return false;
        if(s[0][i] && !top(i, s[0][i])) return false;
        if(s[n + 1][i] && !foot(i, s[n + 1][i])) return false;
    }
    return true;
}
bool DFS(int c) {
    if(c == r) return true;
    for(int x = 1; x <= n; x++) {
        if(!check(P[c].x, P[c].y, x)) continue;
        if(DFS(c + 1)) return true;
        vis[0][P[c].x][x] = vis[1][P[c].y][x] = s[P[c].x][P[c].y] = 0;
    }
    return false;
}
int main() {
    int T; //FIN;
    scanf("%d", &T);
    while(T--) {
        r = 0;
        memset(vis, 0, sizeof(vis));
        scanf("%d", &n);
        for(int i = 0; i <= n + 1; i++) {
            scanf("%s", s[i]);
        }
        if(!check_all() || !DFS(0)) printf("no\n\n");
        else {
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= n; j++) printf("%d", (int)s[i][j]);
                printf("\n");
            }
            printf("\n");
        }
    }
    return 0;
}


你可能感兴趣的:(DFS Gym100827K Towers)