1. 程式人生 > >[POI2015]PIE

[POI2015]PIE

signed cst copy const include event 圖片 AC 第一個

題目描述

一張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 }

[POI2015]PIE