您的位置:首页 > 其它

CodeForces 44J - Triminoes -搜索转构造

2015-11-16 15:08 417 查看
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20077

给你一个n*m的图,图上有‘.’代表挖走了的瓷砖,剩下的是 用w,b分别表示白色黑色的瓷砖

要求找出所有的 “ wbw ”这样的瓷砖,替换成 aaa/bbb/ccc/ddd 任意一个

问你能否把所有的w/b瓷砖按照上述规则替换成   aaa/bbb/ccc/ddd  并且要求,用连续三个字母替换之后的瓷砖不能和相同字母相邻

也就是  不能 aaaaaa 但是可以aaabbb

一开始想dfs ,找出所有 只连接着一个b 的w (此W 必然只能往b的方向填) .我们把这样只有一个方向发展的w成为 度数为1

先找出所有度数为1的w 填掉,再重新搜 不断 找度数为1的w,直到整个图找不到度数为1的w,此时检查 整个图是否填好了

如果没,则不存在方案, 其次 在填的过程中要注意判断 是否能 完整填上三个瓷砖。。。一直wa  on test 32

后来发现,从图的第一行第一列开始 按从左到右从上到下的顺序遍历每一个点,对于每一个W,如果他的左边是‘b’ ,则这个W一定往右填 (否则这个b无法被填上),如果他的左边不是‘b’,那么他只能往下填

按照这样的思路,每一个w只需要判断往下还是往右填,填的时候 判断颜色是否冲突,自己与所要填的方向的瓷砖是否恰为 wbw 

这样  只需要 遍历遍 ,就可以构造出答案

复杂度 O(n*m) 

细节见代码

x#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include<queue>
using namespace std;
int dx_down[8]={-1,0,1,2,3,2,1,0};
int dy_down[8]={0,-1,-1,-1,0,1,1,1};
int dx_right[8]={0,1,1,1,0,-1,-1,-1};
int dy_right[8]={-1,0,1,2,3,2,1,0};

int n,m;
char mp[1005][1005];
char vis[1005][1005];
int col=0;
int getcol()
{
if (col<3)
col++;
else
col=0;
return col;
}
int check(int tmp,int dir,int x,int y) //判断往下填的话,颜色tmp是否与周围有冲突
{
int i;
if (dir==1)
{
for (i=0;i<8;i++)
{
int xx=x+dx_down[i];
int yy=y+dy_down[i];
if (!(xx>=1&&xx<=n&&yy>=1&&yy<=m)) continue;
if (vis[xx][yy]=='a'+tmp) return 1; //need to change col
}
return 0;
}
else if (dir==2)
{
for (i=0;i<8;i++)
{
int xx=x+dx_right[i];
int yy=y+dy_right[i];
if (!(xx>=1&&xx<=n&&yy>=1&&yy<=m)) continue;
if (vis[xx][yy]=='a'+tmp) return 1; //need to change col
}
return 0;
}

}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
getchar();
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
scanf("%c",&mp[i][j]);
}
getchar();
}
int bukeyi=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
if (mp[i][j]=='.'||vis[i][j]) continue;
if (mp[i][j]=='w')
{
col=getcol();
int change_times=5; //如果转了5次颜色 才跳出循环,必然说明不存在合法的颜色可以被填
if (mp[i][j+1]!='b'||(mp[i][j+1]=='b'&&vis[i][j+1]=='b'))//往下填 //mp[i][j]=='b'不一定往右填,这个b可能是bbb中的b而不是wbw的b
{
while(check(col,1,i,j)&&change_times--) //改变颜色直到合法或者换了4次以上
col=getcol();
if (change_times==0)
{bukeyi=1;break;} //找不到合法的颜色
if (!(mp[i][j]=='w'&&mp[i+1][j]=='b'&&mp[i+2][j]=='w')) //判断是否存在wbw
{bukeyi=1;break;}
mp[i][j]=col+'a';
mp[i+1][j]=col+'a';
mp[i+2][j]=col+'a';
vis[i][j]=col+'a';
vis[i+1][j]=col+'a';
vis[i+2][j]=col+'a';
}
else //往you填
{
while(check(col,2,i,j)&&change_times--)
col=getcol();
if (change_times==0)
{bukeyi=1;break;}
if (!(mp[i][j]=='w'&&mp[i][j+1]=='b'&&mp[i][j+2]=='w'))
{bukeyi=1;break;}
mp[i][j]=col+'a';
mp[i][j+1]=col+'a';
mp[i][j+2]=col+'a';
vis[i][j]=col+'a';
vis[i][j+1]=col+'a';
vis[i][j+2]=col+'a';
}

}

}
if (bukeyi) break;
}

if (bukeyi)
{
printf("NO\n");
return 0;
}
printf("YES\n");
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
printf("%c",mp[i][j]);
}
printf("\n");
}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: