您的位置:首页 > 其它

hrbust 1662 凸多边形【最短路SPFA+建图+思维】好题

2016-09-20 19:33 555 查看
凸多边形
Time Limit: 2000 MSMemory Limit: 32768 K
Total Submit: 61(17 users)Total Accepted: 24(17 users)Rating: 







Special Judge: No
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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息