51nod1448 二染色问题(想法题,好题)

题目链接

1448 二染色问题
题目来源:  TopCoder
基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注
一个N*N的网格,初始为白色。现在有一个K*K的印章,每次操作:你可以用印章把网格中一个K*K的子矩形染成黑色或白色。如果一个格子被多次染色,那么后一次染色会覆盖掉前一次的。现在,给你N*N的由黑白两色构成的图案board(board[i][j]为第i行第j列格子的颜色,不是白字母‘W’表示,就是黑由字母‘B’表示),问是否能通过若干次操作,将网格从初始状态染成图案board的样子。如果可以输出"Possible",否则输出"Impossible".
Input
多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成:
每组数据一行两个整数N与K,其中1<=K<=N<=20。
之后N行,每行N个字符,表示board,字符都由‘W’与‘B’构成。
Output
每组数据一行输出,即是否可能染出board图案来。
Input示例
3
4 3
BBBW
BWWW
BWWW
WWWW
2 2
BW
WB
6 2
BWBWBB
WBWBBB
BWBWBB
WBWBBB
BBBBBB
BBBBBB
Output示例
Possible
Impossible
Possible

官方题解

可以尝试逆向思维,最后一块无论是黑是白,都一定是k*k的连通块。倒数第i块,其一部分被最后的i-1块遮挡,其余部分必然同色且分布在k*k的矩形内。因此可以逆向贪心构造,直到每一个小正方形被覆盖为止。


其实这个题就像以前做过的一个贴海报的题目,首先确定一个全部为同色的k*k的块,然后将这些块内的格子标记为访问过了,对于后面的k*k的块,这时候只需要判断除了已经访问的点外,其他的是否为同色,知道找不到这样的块为止,到最后再扫一遍,若存在没被访问的且为black的就说明不存在解决方案。

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,a,n) for (int i=a;i=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector VI;
typedef long long ll;
typedef pair PII;
const ll mod=1000000007;
const int maxn=20+10;
char s[maxn][maxn];
bool vis[maxn][maxn];
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        memset(vis,false,sizeof(vis));
        int n,k;
        scanf("%d%d",&n,&k);
        bool flag=true;
        for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
        while(flag)
        {
            flag=false;
            for(int i=1;i<=n-k+1;i++)
            {
                for(int j=1;j<=n-k+1;j++)
                {
                    int sum1=0,sum2=0;
                    bool f=false;
                    for(int ii=i;ii


你可能感兴趣的:(算法思维)