zoukankan      html  css  js  c++  java
  • 超级码力在线编程大赛初赛 第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);
    }
  • 相关阅读:
    Docker系统知识整理(从安装到熟练操作)
    Dockerfile 文件介绍
    Cmake命令之add_subdirectory介绍
    Cmake实战指南
    cmake的四个命令:add_compile_options、add_definitions、target_compile_definitions、build_command
    cmake:选择编译器及设置编译器选项
    Task异常
    单元测试误区
    网络的核心概念
    java~使用枚举来实现接口的多态
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/13692638.html
Copyright © 2011-2022 走看看