洛谷P3585 [POI2015]PIE

Posted 小时のblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3585 [POI2015]PIE相关的知识,希望对你有一定的参考价值。

传送门

题目大意:有个n*m的格子图,要求‘x‘点要被染成黑色

有个a*b的印章,‘x‘是可以染色的印章上的点。

要求用印章去染色格子

(1)印章不可以旋转。

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

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

题解:模拟

 

从题目中可以看出,一定要让印章的左上角对应目前n*m方

格中未染色的左上角。因为要求不能重复染色,可以每染完

一个格子就把它赋值为0.(待染色为1)。

 

开始纯模拟,没有任何优化的代码。

加了个读入优化还是T了两个点,3000ms+

技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1022
using namespace std;
int n,m,a,b,fa,fb,cnt,q;
int map[N][N],yz[N][N];
char s[N];
inline int read(int &x){
    char ch=getchar();x=0;int f=1;
    for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-0;
    x=x*f;
}
void init(){
    memset(map,0,sizeof(map));
    memset(yz,0,sizeof(yz));
    cnt=0;fa=0;fb=0;
}
bool check(int x,int y){
    int xx=x-fa,yy=y-fb;
    for(int i=1;i<=a;i++){
        for(int j=1;j<=b;j++){
            if(yz[i][j]==0)continue;
            int rx=xx+i,ry=yy+j;
            if(rx<0||ry<0||rx>n||ry>m||map[rx][ry]==0)return false;
            map[rx][ry]=0;cnt--;
        }
    }
    return true;
}
int main(){
    scanf("%d",&q);
    while(q--){
        init();bool flag=false;
       // scanf("%d%d%d%d",&n,&m,&a,&b);
      //  n=read();m=read();a=read();b=read();
       read(n);read(m);read(a);read(b);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
             if(s[j]==x)map[i][j]=1,cnt++;
        }
        for(int i=1;i<=a;i++){
            scanf("%s",s+1);
            for(int j=1;j<=b;j++){
                if(s[j]==.)continue;
                if(!fa&&!fb)fa=i,fb=j;
                yz[i][j]=1;
            }
        }
        for(register int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(map[i][j]){
                    if(check(i,j)==0){
                        printf("NIE\n");
                        flag=true;break;
                    }
                    if(cnt==0){
                        printf("TAK\n");
                        flag=true;break;
                    }
                }
            }
            if(flag)break;
        }
    }
    return 0;
}
80

看了题解... 想到以前做靶型数独这个题,把未填数的格子放到一个结构体里。

w[i].x,w[i].y分别表示第i个没有填数格子的横纵坐标。

这样的好处是不用遍历整张图,就找到了没填数的格子。

这个题也是这样....

上面的代码不仅遍历了一遍要染色的图,还遍历了整个印章。

最差的情况是10^12...遍历要染色的10^6,印章10^6。

所以把要染色的点和能染色的点抽离出来,放到结构体里。

很好的一个优化,188ms。

ps:某一行后面+***,可以这样理解..

yz[1].x+xx=x,yz[1].y+yy=y.

说明印章的左上角的可以染色的点,要对应

n*m的棋盘要加xx和yy,那么其他可以染色的点也要加这两个数

来对应他们要染色的点。

代码:

技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1009
using namespace std;
int n,m,a,b,cnt_black,yz_black,q;
char s[N];
int map[N][N];
struct Make_Black{
    int x,y;
}gz[N*N],yz[N*N];
bool check(int x,int y){
    int xx=x-yz[1].x,yy=y-yz[1].y;  //*** 
    for(int i=1;i<=yz_black;i++){  
        int nx=yz[i].x+xx,ny=yz[i].y+yy;
        if(nx<0||nx>n||ny<0||ny>m||map[nx][ny]==0)return false;
        map[nx][ny]=false;
    }
    return true;
}
int main(){
    scanf("%d",&q);
    while(q--){
        bool flag=false;
        cnt_black=yz_black=0;
        scanf("%d%d%d%d",&n,&m,&a,&b);
        memset(map,0,sizeof(map));
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            for(int j=1;j<=m;j++)
             if(s[j]==x){
                 gz[++cnt_black].x=i;gz[cnt_black].y=j;
                 map[i][j]=true;
             }
        }
        for(int i=1;i<=a;i++){
            scanf("%s",s+1);
            for(int j=1;j<=b;j++)
             if(s[j]==x)yz[++yz_black].x=i,yz[yz_black].y=j;
        }
        for(int i=1;i<=cnt_black;i++){
            if(map[gz[i].x][gz[i].y])
             if(check(gz[i].x,gz[i].y)==0){
                 flag=true;
                 printf("NIE\n");break;
             }
        }
        if(!flag)printf("TAK\n");
    }
    return 0;
}
View Code

 

以上是关于洛谷P3585 [POI2015]PIE的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P3588 - [POI2015]Pustynia

BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze do?y

BZOJ2938 & 洛谷2444:[POI2000]病毒——题解

AC日记——[POI2008]BLO-Blockade 洛谷 [POI2008]BLO-Blockade

[洛谷P3501] [POI2010]ANT-Antisymmetry

洛谷 P3467 [POI2008]PLA-Postering