zoukankan      html  css  js  c++  java
  • [POI2015]PIE

    题目描述

    一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色。你有一个a*b的印章,有些格子是凸起(会沾上墨水)的。你需要判断能否用这个印章印出纸上的图案。印的过程中需要满足以下要求:(1)印章不可以旋转。(2)不能把墨水印到纸外面。(3)纸上的同一个格子不可以印多次。

    输入输出格式

    输入格式:

    第一行一个整数q(1<=q<=10),表示测试点数量。接下来q个测试点,每个测试点中:第一行包含4个整数n,m,a,b(1<=n,m,a,b<=1000)。接下来n行,每行m个字符,描述纸上的图案。'.'表示留白,'x'表示需要染黑。接下来a行,每行b个字符,描述印章。'.'表示不沾墨水,'x'表示沾墨水。

    输出格式:

    对于每个测试点,输出TAK(是)或NIE(否)。

    输入输出样例

    输入样例#1: 
    2
    3 4 4 2
    xx..
    .xx.
    xx..
    x.
    .x
    x.
    ..
    2 2 2 2
    xx
    xx
    .x
    x.
    输出样例#1: 
    TAK
    NIE
     

    说明

    一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色。

    你有一个a*b的印章,有些格子是凸起(会沾上墨水)的。你需要判断能否用这个印章印出纸上的图案。印的过程中需要满足以下要求:

    (1)印章不可以旋转。

    (2)不能把墨水印到纸外面。

    (3)纸上的同一个格子不可以印多次。

    提交地址 : Luogu3585;

    模拟水题

    调了半天(真是半天);

    首先,我们肯定要把印章的左上角第一个有印的地方,对准画布上第一个左上角地方;

    显然可以暴力O(n^4), T飞;

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    inline char nc()
    {
        static const int BS = 1 << 22;
        static unsigned char buf[BS],*st,*ed;
        if(st == ed) ed = buf + fread(st=buf,1,BS,stdin);
        return st == ed ? EOF : *st++;
    }
    //#define getchar nc
    inline int read()
    {
        int res=0;bool flag=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')flag=1;ch=getchar();
        }while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch-'0');ch=getchar();
        }return flag?-res:res;
    }
    
    int q;
    int n, m, x, y;
    int a[1010][1010];
    int tab[1010][1010];
    int num, fx, fy;
    
    bool check(int xx, int yy)
    {
        xx -= fx - 1, yy -= fy - 1;
        for (register int i = 1 ; i <= x ; i ++)
        {
            for (register int j = 1 ; j <= y ; j ++)
            {
                if (tab[i][j] == 0) continue; 
                if (xx + i - 1 <= 0 or xx + i - 1 > n or yy + j - 1 <= 0 or yy + j - 1 > m or a[xx+i-1][yy+j-1] == 0) return 0;
                a[xx+i-1][yy+j-1] = 0;
                num--;
            }
        }
        return 1;
    }
    
    int main()
    {
        q = read();
        while (q--)
        {
            num=0;
            n=read(), m=read(), x=read(), y=read();
            fx = fy = 0;
            for (register int i = 1 ; i <= n ; i ++)
            {
                for (register int j = 1 ; j <= m ; j ++)
                {
                    char ch;
                    cin >> ch;
                    if (ch == '.') a[i][j] = 0;
                    else a[i][j] = 1, num++;
                }
            }
            for (register int i = 1 ; i <= x ; i ++)
            {
                for (register int j = 1 ; j <= y ; j ++)
                {
                    char ch;
                    cin >> ch;
                    if (ch == '.') tab[i][j] = 0;
                    else
                    {
                         tab[i][j] = 1;
                         if (!fx) fx = i, fy = j;
                    }                
                }
            }
            
            for (register int i = 1 ; i <= n ; i ++)
            {
                for (register int j = 1 ; j <= m ; j ++)
                {
                    if (!a[i][j]) continue;
                    if (!check(i, j))
                    {
                        puts("NIE");
                        goto End;
                    }
                    if (num == 0)
                    {
                        puts("TAK");
                        goto End;
                    }
                }
            }
            puts("NIE");
            End:;
        }
        return 0;
    }
    zZhBr

    现在我们考虑优化;

    我们把时间主要浪费在哪里了?

    不停地循环找印章!

    显然我们在印章和图里有很多不需要的点, 我们花费了太多时间浪费在它们身上;

    那不如干脆来一个链表,直接把有用的点穿起来,这样查询十分省时间!

    轻松A掉

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 
      7 inline char nc()
      8 {
      9     static const int BS = 1 << 22;
     10     static unsigned char buf[BS],*st,*ed;
     11     if(st == ed) ed = buf + fread(st=buf,1,BS,stdin);
     12     return st == ed ? EOF : *st++;
     13 }
     14 #define nc getchar
     15 inline int read()
     16 {
     17     int res=0;bool flag=0;char ch=nc();
     18     while(!isdigit(ch)){if(ch=='-')flag=1;ch=nc();
     19     }while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch-'0');ch=nc();
     20     }return flag?-res:res;
     21 }
     22 
     23 int q;
     24 int n, m, x, y;
     25 struct MAP
     26 {
     27     int x, y;
     28 }a[1010*1010];
     29 int cnt = 1;
     30 struct TAB
     31 {
     32     int x, y;
     33 }tab[1010*1010];
     34 int now = 1;
     35 int mp[1010][1010];
     36 
     37 inline bool check(int xx, int yy)
     38 {
     39     xx -= tab[1].x - 1, yy -= tab[1].y - 1;
     40     for (register int i = 1 ; i <= now ; i ++)
     41     {
     42         int tx = xx + tab[i].x - 1, ty = yy + tab[i].y - 1;
     43         if (tx <= 0 or tx > n or ty <= 0 or ty > m) return 0;
     44         if (mp[tx][ty] == 0) return 0;
     45         mp[tx][ty] = 0;
     46     }
     47     return 1;
     48 }
     49 
     50 int main()
     51 {
     52     q = read();
     53     while (q--)
     54     {
     55         n=read(), m=read(), x=read(), y=read();
     56         cnt = now = 1;
     57         for (register int i = 1 ; i <= n ; i ++)
     58         {
     59             for (register int j = 1 ; j <= m ; j ++)
     60             {
     61                 char ch;
     62                 cin >> ch;
     63                 if (ch == '.') mp[i][j] = 0;
     64                 else 
     65                 {
     66                     mp[i][j] = 1;
     67                     a[cnt].x = i;
     68                     a[cnt++].y = j;
     69                 }
     70             }
     71         }
     72         for (register int i = 1 ; i <= x ; i ++)
     73         {
     74             for (register int j = 1 ; j <= y ; j ++)
     75             {
     76                 char ch;
     77                 cin >> ch;
     78                 if (ch == '.') continue;
     79                 else
     80                 {
     81                      tab[now].x = i;
     82                      tab[now++].y = j;
     83                 }                
     84             }
     85         }
     86         cnt--, now--;
     87         for (register int i = 1 ; i <= cnt ; i ++)
     88         {
     89             if (mp[a[i].x][a[i].y] == 0) continue;
     90             if (!check(a[i].x, a[i].y))
     91             {
     92                 puts("NIE");
     93                 goto End;
     94             }
     95         }
     96         
     97         puts("TAK");
     98         End:;
     99     }
    100     return 0;
    101 }
  • 相关阅读:
    实验 6 数组1输出最大值和它所对应的下标
    实验5第二题
    实验5第一题
    作业 3 应用分支与循环结构解决问题 判断是否闰年
    心得与体会1
    第七章
    第六章
    第五章
    第四章
    第一章
  • 原文地址:https://www.cnblogs.com/BriMon/p/9117772.html
Copyright © 2011-2022 走看看