您的位置:首页 > 编程语言 > C语言/C++

RQNOJ190 拦截匪徒 (重庆一中高2018级信息学竞赛测验2) 解题报告

2016-07-14 15:36 239 查看
【问题描述】

某城市的地图是一个由N个点组成的无向图,每个点代表一个区。现在p区发生抢劫案,而警察为了截住劫匪须埋伏在一个劫匪必经区域。由于不知道劫匪会向哪个区逃窜,所以市长要求对于任意一个劫匪可能逃向的区j,找出一个可以拦截劫匪的区域k(k!=p,k!=j),即劫匪从p区逃向j区,必须经过k区。由于地区j可能为匪徒的老巢所在,所以警察希望能在路上拦截住土匪,而不是在j区抓获。

【输入格式】

第一行N,p,接下来得为N*N的矩阵A,A[i][j]=1,表示i与j右路相连,A[i][j]=0则没有。

【输出格式】

输出N-1行,输出警察应在哪个些置埋伏,按j=1、2、…p-1、p+1、…N的顺序输出,若有多点,由小到大顺序输出。如果没有合适的埋伏位置,或者在p与j根本就不连通,则输出No。

【输入输出样例1】

catch.in

5 1

0 1 1 0 0

1 0 1 1 0

1 1 0 0 0

0 1 0 0 1

0 0 0 1 0

catch.out

No

No

2

2 4

【数据范围】

1<=N,p<=300

做题思路(错解):拿到这道题时,以为只要枚举劫匪逃向的区j,然后进行一次BFS,看由j到p经过的点,结果卡在怎么找由j到p经过的点,导致使用了错误的方法。

解题思路(正解):根据题意,依次枚举劫匪逃向的区j和拦截劫匪的区k,每枚举一组j、k,在删除k的情况下,从p点出发进行BFS,看p能否到达j,若能则k不是拦截劫匪的区域,若不能则满足题意输出答案。需要注意的是,在枚举之前,需先从p出发进行BFS,找出p点出发能到的点,如果枚举的区j不能到达p,则直接输出No。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=305;
int N,p;
int a[maxn][maxn];
vector<int>g[maxn];
int vis1[maxn],vis2[maxn];
void BFS(int i,int *vis)  //找从i点出发能到达的点
{
queue<int>q;
q.push(i);
vis[i]=1;
while(!q.empty())
{
int i=q.front();  q.pop();
for(int k=0;k<g[i].size();k++)
{
int j=g[i][k];
if(vis[j])  continue;
q.push(j);
vis[j]=1;
}
}
}
int main()
{
freopen("catch.in","r",stdin);
freopen("catch.out","w",stdout);
scanf("%d%d",&N,&p);
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=N;i++)
for(int j=i+1;j<=N;j++)
if(a[i][j]==1)
{
g[i].push_back(j);
g[j].push_back(i);
}
memset(vis1,0,sizeof(vis1));
BFS(p,vis1);  //看p点能到达哪些点
for(int i=1;i<=N;i++)if(i!=p)
{
if(vis1[i]==0) //p点不能到达i点
{
printf("No\n");
continue;
}
int ok=0;
for(int j=1;j<=N;j++)if(j!=i && j!=p)
{
memset(vis2,0,sizeof(vis2));
vis2[j]=1; //删除j点
BFS(p,vis2);
if(vis2[i]==0)
{
ok=1;
printf("%d ",j);
}
}
if(ok==0)  printf("No");  //如果p点与i点之间有一条直接连通的路,则输出No
printf("\n");
}
return 0;
}


考后反思:做题时,想得不能太复杂,应该从最简单的暴力枚举开始想,也许有些题就需要用这种方法。如果枚举一个变量不行,就要考虑再枚举一个,不能只停留在只枚举一个变量去找方法解决。在删除条件(假删除)时,应选择最简单删除方法,往往删的方法难了就容易错。考虑问题的情况时,要考虑全面,完整,不能想到一半就开跑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ RQNOJ