hrbust 1662 凸多边形【最短路SPFA+建图+思维】好题
2016-09-20 19:33
555 查看
凸多边形 | ||||||
| ||||||
Description | ||||||
有一个n x m 的方格阵。开始时,所有的方格的颜色都是白色的。小z已经把其中的一些方格(至少1个)涂成了黑色。如果在方格中从任意一个黑色方格沿着黑色方格走到另一个黑色方格最多只需要拐弯一次的话,我们就称黑色方格组成区域为凸多边形。如下图所示,左边是凸多边形而右边的不是. 现在你需要判断一个方格阵中黑色的格子组成的图形是不是凸多边形。 | ||||||
Input | ||||||
多组测试数据。 每组测试数据第一行输入两个整数n,m表示方格阵的行数和列数(1<=n,m<=50),接下来的n行每行是一个长度为m由‘W’或者‘B’组成的字符串,表示方格的状态分别为白色或者黑色。 | ||||||
Output | ||||||
对于每组数据,如果图形是凸多边形则输出”YES”,否则输出”NO”。每组输出占一行。 | ||||||
Sample Input | ||||||
3 4 WWBW BWWW WWWB 3 1 B B W | ||||||
Sample Output | ||||||
NO YES | ||||||
Author | ||||||
`Wind @hrbust |
看到好多人用暴力判断写的,好复杂- -。
1 、我们将拐弯次数设定为边权,将不用拐弯的两点间建立一条边,边权值设定为1.那么如果从某个点i,到某个点j的最短路长度为2,那么说明从点i到点j至少需要拐弯一次,同理,如果某点i到某点j的最短路长度为3,那么说明点i到点j至少需要拐弯两次。那么根据这个特性,我们将每两个黑色的点,必须是这两个点同行或者同列,并且中间没有白色的格子阻拦,那么将这两个点之间建立一条边,边权设定为1.
2、那么我们剩下的任务就是跑contn(表示黑色格子的个数)次单源最短路,如果我们使用nlogn算法的Dij是一定不会超时的,这里的实现还是用的SPFA,(过了就行呗)。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int next;
int w;
}e[2500000];
char a[150][150];
int num[150][150];
int head[25000];
int vis[25000];
int dis[25000];
int n,m,contn,cont;
void add(int from,int to)
{
e[cont].to=to;
e[cont].w=1;
e[cont].next=head[from];
head[from]=cont++;
}
void getmap()
{
contn=0;
cont=0;
memset(head,-1,sizeof(head));
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]=='B')
{
num[i][j]=++contn;
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]!='B')continue;
for(int k=i+1;k<n;k++)
{
if(a[k][j]=='B')
{
add(num[i][j],num[k][j]);
}
else if(a[k][j]=='W')break;
}
for(int k=i-1;k>=0;k--)
{
if(a[k][j]=='B')
{
add(num[i][j],num[k][j]);
}
else if(a[k][j]=='W')break;
}
for(int k=j-1;k>=0;k--)
{
if(a[i][k]=='B')
{
add(num[i][j],num[i][k]);
}
else if(a[i][k]=='W')break;
}
for(int k=j+1;k<m;k++)
{
if(a[i][k]=='B')
{
add(num[i][j],num[i][k]);
}
else if(a[i][k]=='W')break;
}
}
}
}
int SPFA(int ss)
{
queue<int >s;
s.push(ss);
for(int i=1;i<=contn;i++)dis[i]=0x3f3f3f3f;
dis[ss]=0;
memset(vis,0,sizeof(vis));
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
for(int i=1;i<=contn;i++)
{
if(dis[i]==0x3f3f3f3f)return 0;
if(dis[i]>2)return 0;
}
return 1;
}
void Slove()
{
int flag=0;
for(int i=1;i<=contn;i++)
{
if(SPFA(i)==0)
{
flag=1;break;
}
}
if(flag==1)
{
printf("NO\n");
}
else printf("YES\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
}
getmap();
Slove();
}
}
相关文章推荐
- 百度笔试-房屋群
- Docker-搭建简单的应用栈
- 无限轮播加小圆点
- 【经典算法探究】:B树,B+树,B-树,B*树
- LeetCode 172. Factorial Trailing Zeroes题解
- http协议没有已注册的程序
- PHP学习笔记:用mysqli连接数据库
- yii2自定义500错误
- 模板方法模式
- 字节流转化为字符流输出
- POJ 3041 POJ 3041
- XCTF2016 类似培根
- ibatis和hibernate的区别
- Ibatis的级联实现
- cocos2dx游戏性能优化之对象池
- 浅谈Activity的四种启动模式
- 21 RadioGroup ListFragment
- Android相机相册的调用,图片的存储删除
- STL容器 -- Vector
- 21 RadioGroup ListFragment