zoukankan      html  css  js  c++  java
  • D-多连块拼图

    多连块是指由多个等大正方形边与边连接而成的平面连通图形。
    – 维基百科

    给一个大多连块和小多连块,你的任务是判断大多连块是否可以由两个这样的小多连块拼成。小多连块只能平移,不能旋转或者翻转。两个小多连块不得重叠。左下图是一个合法的拼法,但右边两幅图都非法。中间那幅图的问题在于其中一个小多连块旋转了,而右图更离谱:拼在一起的那两个多连块根本就不是那个给定的小多连块(给定的小多连块画在右下方)。
    这里写图片描述
    Input
    输入最多包含20组测试数据。每组数据第一行为两个整数n和m(1<=m<=n<=10)。以下n行描述大多连块,其中每行恰好包含n个字符或者.,其中表示属于多连块,.表示不属于。以下m行为小多连块,格式同大多连块。输入保证是合法的多连块(注意,多连块至少包含一个正方形)。输入结束标志为n=m=0。
    Output
    对于每组测试数据,如果可以拼成,输出1,否则输出0。
    Sample Input
    4 3
    .**.
    ****
    .**.
    ….
    **.
    .**

    3 3
    ***
    *.*
    ***
    *..
    *..
    **.
    4 2
    ****
    ….
    ….
    ….
    *.
    *.
    0 0
    Sample Output
    1
    0
    0
    Hint

    分析:
    因为题中说不能旋转,所以枚举第一块和第二块的位置即可;
    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    const int N = 10 + 5;
    
    char goal[N][N];
    char mat[N][N],st[N][N],tmp[N][N];
    struct node{
        int x,y;
    }Node[105];
    int cnt,n,m;
    void To_left_top(){
        int dx=0,dy=0,i,j;
        for(i=0;i<m;i++){
            for(j=0;j<m;j++) if(st[i][j]=='*') break;
            if(j == m) dx--;
            else break;
        }
        for(j=0;j<m;j++){
            for(i=0;i<m;i++) if(st[i][j]=='*') break;
            if(i == m) dy--;
            else break;
        }
        for(int i=0;i<cnt;i++) Node[i].x+=dx,Node[i].y+=dy;
    }
    void print(){
       for(int i=0;i<cnt;i++){
                mat[Node[i].x][Node[i].y] = '*';
            }
            for(int i=0;i<m;i++){
                for(int j=0;j<m;j++){
                    printf("%c",mat[i][j]);
                    if(j==m-1) printf("
    ");
                }
            }
    }
    bool match(){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            if(goal[i][j]!=tmp[i][j]) return false;
        return true;
    }
    bool next_add(int x,int y){
        memcpy(tmp,mat,sizeof(mat));
        for(int i=0;i<cnt;i++){
            int newx = x + Node[i].x;
            int newy = y + Node[i].y;
            if(newx>=n || newy>=n || tmp[newx][newy]=='*') return false;
            tmp[newx][newy] = '*';
        }
        if(match()) return true;
        else return false;
    }
    bool add(int x,int y){
        memset(mat,'.',sizeof(mat));
        for(int i=0;i<cnt;i++){
            int newx = Node[i].x + x;
            int newy = Node[i].y + y;
            if(newx>=n || newy>= n) return false;
            mat[newx][newy] = '*';
        }
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            if(!next_add(i,j)) continue;
            else return true;
        }
        return false;
    }
    bool solve(){
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++){
            if(!add(i,j)) continue;
            else return true;
        }
        return false;
    }
    int main(){
        while(scanf("%d %d",&n,&m)==2 &&(n||m)){
            cnt = 0;
            for(int i=0;i<n;i++) scanf("%s",goal[i]);
            for(int i=0;i<m;i++){
                scanf("%s",st[i]);
                for(int j=0;j<m;j++) if(st[i][j]=='*') Node[cnt].x = i,Node[cnt++].y = j;
            }
            To_left_top();
            printf("%s
    ",solve()?"1":"0");
        }
    }
  • 相关阅读:
    HDU5000 (DP + 规律)
    HDU5127 神坑题---vector 、 list 、 deque 的用法区别
    HDU5128 细心、细心、细心
    dij单源最短路纯模板
    POJ 1236 SCC+缩点
    SCC(强连通分量)
    用树状数组求数组内的逆序对数
    HDU 1811 并查集
    大数模板,只要不是手敲,非常好用
    市赛
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7347691.html
Copyright © 2011-2022 走看看