超级码力在线编程大赛初赛 第4场 1.十字绣

https://tianchi.aliyun.com/oj/15193368247341694/87525024802738980

搜索

我用的是搜索行,检验列

搜行的时候只考虑行的限制,检验列的时候只考虑列的限制

每次只考虑第一行到当前这一行,以及到当前列是不是满足要求

搜索每一个连续区间

假设现在是第x行的第y个连续区间

先将这一个连续区间定好位置

假设本行上一个连续区间到了第a列,这一个连续区间到了第b列

然后检验本行[a+1,b]内的每一列i,如果第i列从第1行到这一行,都还不违背列的限制

那就认为是合法的

注意如果到了最后一行,要判断是否已经满足本列的限制

剪枝只加了1个

预处理每一行每一个连续段后面至少需要多少列

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#define N 27

int n,m;
int hh[N][N],sh[N],ll[N][N],sl[N];

bool mp[N][N];

int sneed[N][N];

int ok=0;

bool check(int x,int y)
{
    int now=1,tmp=0;
    for(int i=1;i<=x;++i)
        if(mp[i][y])
        {
            if(now>sl[y]) return false;
            tmp++;
            if(tmp>ll[y][now]) return false;
        }
        else
        {
            if(!tmp) continue;
            if(tmp!=ll[y][now]) return false;
            tmp=0;
            now++;
        }
    if(x==n) 
    {
        if(tmp) return (now==sl[y] && tmp==ll[y][now]);
        else return now==sl[y]+1;
    }
    return true;
}

bool color(int x,int sum,int pos,int last)
{
    int t=pos+sum-1;
    for(int i=pos;i<=t;++i) mp[x][i]=true;
    for(int i=max(1,last+1);i<=t;++i)
        if(!check(x,i)) return false;
    return true;
}

void dfs(int x,int y,int last)
{
    if(x==n+1)
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=m;++j)
                if(mp[i][j]) printf("*");
                else printf(".");
            printf("
");
        }
        exit(0);
    }
    if(y>sh[x])
    {
        dfs(x+1,1,-1);
        return;
    }
    bool tmp[N][N];
    for(int i=last+2;i+sneed[x][y]-1<=m;++i)
    {
        memcpy(tmp,mp,sizeof(mp));
        if(color(x,hh[x][y],i,last))
        {
            /*for(int k=1;k<=n;++k)
            {
                for(int j=1;j<=m;++j) 
                    if(mp[k][j]) printf("*");
                    else printf(".");
                printf("
"); 
            }
            printf("

");
            ok++;*/
            if(y==sh[x]) dfs(x+1,1,-1);
            else dfs(x,y+1,i+hh[x][y]-1);
        }
        memcpy(mp,tmp,sizeof(tmp));
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&sh[i]);
        for(int j=1;j<=sh[i];++j) scanf("%d",&hh[i][j]);
    }
    for(int i=1;i<=m;++i)
    {
        scanf("%d",&sl[i]);
        for(int j=1;j<=sl[i];++j) scanf("%d",&ll[i][j]); 
    }
    for(int i=1;i<=n;++i)
        for(int j=sh[i];j;--j)
            if(j==sh[i]) sneed[i][j]=hh[i][j];
            else sneed[i][j]=sneed[i][j+1]+1+hh[i][j];
    dfs(1,1,-1);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/13692638.html