【2019.11.7】

题目    题解

题面

小A是一名画家。现在有一张大小为n * m的网格图,小A用K种颜色在网格图上作画。其中第i种颜色编号为i,初始时网格图中每个格子都没有颜色,编号为0。已知每种颜色小A都会使用且只使用一次,但使用的顺序是未知的。使用一种颜色时需要选定一个连续的子矩阵,将该子矩阵涂上这种颜色。后涂的颜色会覆盖之前的颜色。现在给出小A画完后的图,问有多少种颜色可能是小A最先使用的。


题解、总结

*正解就是:处理出每个颜色的四个顶点,枚举整个颜色块,如果块内有一个不合法的颜色那么k--并标记它(避免重复减去同一种颜色的可能)。

*错误1:没睡好+起床姿势不对引发的惨案->下划线的地方全部没看到->一定要按计划做每件事,专心认真投入地做一件事;要有考试的感觉

*错误2:STL不太会,存储不了全部数据->存储数据经常考小点,要熟练

*错误3:一个比较简单的模拟因为没想清楚就开始打所以途中漏洞百出,浪费很多时间->主要也是因为状态不好,但多读题多遍理解多研究样例多出几组数据,说过多少遍呢


 代码

*70分的未存储全部数据:

#include<bits/stdc++.h>
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Dfor(i,r,l) for(int i=r;i>=l;i--)
using namespace std;
const int M=1e5+5;
int n,m,k,cnt,clr[M];
bool vis[M],f[M];
struct node{
    int up,don,le,ri;
}col[M];
inline ll read(){
    ll f=1,sum=0;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();}
    return f*sum;
}
int main(){
    freopen("paint.in","r",stdin);
    freopen("paint.out","w",stdout);
    n=read(),m=read(),k=read();
    ll a[n+10][m+10];
    if(n==1&&m==1){
        cout<<k-1<<endl;return 0;
    }
    memset(a,0,sizeof(a));
    For(i,1,k) col[i].up=1e9,col[i].le=1e9;
    For(i,1,n){
        For(j,1,m){
            a[i][j]=read();
            int colo=a[i][j];
            col[colo].up=min(col[colo].up,i);
            col[colo].don=max(col[colo].don,i);
            col[colo].le=min(col[colo].le,j);
            col[colo].ri=max(col[colo].ri,j);
            if(!f[colo]) clr[++cnt]=colo,f[colo]=1;
        }
    }
    vis[0]=1;
    For(i,1,cnt){
        int j=clr[i];
        if(!j)continue;
        For(p,col[j].up,col[j].don){
            For(q,col[j].le,col[j].ri){
                if(!vis[a[p][q]]&&a[p][q]!=j){
                    vis[a[p][q]]=1;
                    k--;
                }
            }
        } 
    }
    printf("%d
",k);
    return 0;
}
View Code

*100分:

题面


题解、反思


代码

题面


题解、反思


代码

原文地址:https://www.cnblogs.com/jian-song/p/11812269.html