3741. 【TJOI2014】拼图(puzzle)

Description

3741. 【TJOI2014】拼图(puzzle)

Solution

直接暴力。

用结构体记录好每片拼图的构成,然后对于每片拼图,遍历左上角放的位置,判断能否放置,如果能放就放。最后判断这个正方形是否被填满。

一点点小的优化:因为当结果超过 1 时,不要求总方案数,因此当我们得到两种方案后,就可以直接结束递归了。

当然这题也是可以用状压的。

Code

#include<cstdio>
#define N 20
using namespace std;
struct node
{
    int r,c,p[5][5];
}a[N];
int n,ansnum,ans[5][5],d[5][5];
bool flag;
char s[5];
bool ful()
{
    for (int i=1;i<=4;++i)
        for (int j=1;j<=4;++j)
            if (!d[i][j]) return false;
    return true;
}
bool check(int x,int y,int id)
{
    for (int i=1;i<=a[id].r;++i)
        for (int j=1;j<=a[id].c;++j)
        {
            if (!a[id].p[i][j]) continue;
            if (x+i-1>4) return false;
            if (y+j-1>4) return false;
            if (d[x+i-1][y+j-1]) return false;
        }
    return true;
}
void setin(int x,int y,int id,int num)
{
    for (int i=1;i<=a[id].r;++i)
        for (int j=1;j<=a[id].c;++j)
        {
            if (!a[id].p[i][j]) continue;
            d[x+i-1][y+j-1]=num;
        }
}
void dfs(int x)
{
    if (flag) return;
    bool k=ful();
    if (k||x>n)
    {
        if (k)
        {
            if (ansnum)
            {
                ++ansnum;
                flag=true;
            }
            else
            {
                ansnum=1;
                for (int i=1;i<=4;++i)
                    for (int j=1;j<=4;++j)
                        ans[i][j]=d[i][j];
            }
        }
        return;
    }
    for (int i=1;i<=4;++i)
        for (int j=1;j<=4;++j)
        {
            if (check(i,j,x))
            {
                setin(i,j,x,x);
                dfs(x+1);
                setin(i,j,x,0);
            }
        }
    dfs(x+1);
}
int main()
{
    freopen("puzzle.in","r",stdin);
    freopen("puzzle.out","w",stdout);
    while (scanf("%d",&n)!=EOF)
    {
        for (int i=1;i<=n;++i)
        {
            scanf("%d%d",&a[i].r,&a[i].c);
            for (int j=1;j<=a[i].r;++j)
            {
                scanf("%s",s+1);
                for (int k=1;k<=a[i].c;++k)
                    a[i].p[j][k]=s[k]-'0';
            }
        }
        ansnum=0;
        flag=false;
        for (int i=1;i<=4;++i)
            for (int j=1;j<=4;++j)
                ans[i][j]=d[i][j]=0;
        dfs(1);
        if (ansnum==0) printf("No solution\n");
        else if (ansnum>=2) printf("Yes, many!\n");
        else
        {
            printf("Yes, only one!\n");
            for (int i=1;i<=4;++i)
            {
                for (int j=1;j<=4;++j)
                    printf("%d",ans[i][j]);
                printf("\n");
            }
        }
    }
    return 0;
}
上一篇:最强的疯狂java学习路线图,javaEE学习者必看


下一篇:twemproxy源码解析-前言:特性简介