[POI2015]PIE
阿新 • • 發佈:2018-05-31
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 << 22zZhBr; 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; }
現在我們考慮優化;
我們把時間主要浪費在哪裏了?
不停地循環找印章!
顯然我們在印章和圖裏有很多不需要的點, 我們花費了太多時間浪費在它們身上;
那不如幹脆來一個鏈表,直接把有用的點穿起來,這樣查詢十分省時間!
輕松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