题解:P8073 [COCI2009-2010#7] BAKICE

水题。

思路

n100n\le 100,考虑直接模拟。

我们首先预处理出人和座位之间的距离,数组记为 ee

然后把 ee 按距离排序。

对于一条边,连接人 xx 和座椅 yy,我们这么处理:

  • xx 已经坐上座位。显然一定有一个座位,使得在这个人的位置出发,距离更短。所以这个座位不是答案。
  • xx 还没有坐上座位,同时座位 yy 还没有人坐。那么人 xx 坐在座位 yy 上一定最优。证明:如果再往后走,还有一个人 xx 可以坐的座位,人 xx 到这个座位的距离一定更长。
  • xx 还没有坐上座位,但是这个座位 yy 被另一个人 zz 坐了,并且这个人 xx 到座位 yy 的距离比另一个人 zz 到座位 yy 的距离大。这样这个人 xx 就无法坐在这个座位上,只能再往后找。
  • xx 还没有坐上座位,但是这个座位 yy 被另一个人 zz 做了,但是这个人 xx 和另一个人 zz 到这个座位 yy 的距离一致。自然会发生爆炸。

于是可以写出代码:

for(int i=1;i<=cnt;i++){
		int u=e[i].u,v=e[i].v;
		if(vis[u]){
			continue;
		}
		if(!zhan[v]){
			vis[u]=v;
			zhan[v]=u;
			sum[v]++;
		}
		else{
			double dis=e[i].dis;
			double dis1=sqrt((sx[v]-px[zhan[v]])*(sx[v]-px[zhan[v]])+(sy[v]-py[zhan[v]])*(sy[v]-py[zhan[v]]));
			if(dis==dis1){
				zhan[v]=u;
				vis[u]=v;
				sum[v]++;
				ans++;
			}
		}
	}

但是这个代码是错误的。原因是:如果 nn 个人同时抢一个座位,这个代码会统计 n1n-1 次。很显然:除了第一个人,后面所有人枚举到这个位置,都会有一个人在这上面,触发 ans++ 的条件。

举个例子:

3 3
.X.
XLX
.X.

很显然四个人都会抢一个位置,发生一次爆炸,但是这个代码会输出 33

因为我们在枚举到第二个人时,判断第一个人占掉了,距离一致,答案增加;在枚举到第三个人时,判断第二个人占掉了,距离一致,答案增加;在枚举到第四个人时,判断第三个人占掉了,距离一致,答案也增加。

如何避免这个问题?我们需要一个 sum 数组,统计抢这个位置的人数。如果多于 11,则会发生爆炸,答案增加。

代码

#include<bits/stdc++.h>
using namespace std;
struct node{
	int u,v;
	double dis;
}e[10005];
char ch[105][105];
int n,m,cnt1,cnt2,cnt;
int px[10005],py[10005],sx[10005],sy[10005];
int vis[10005];
bool cmp(node _,node __){
	return _.dis<__.dis;
}
int zhan[10005],sum[10005];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>ch[i][j];
			if(ch[i][j]=='X'){
				px[++cnt1]=i;
				py[cnt1]=j;
			}
			if(ch[i][j]=='L'){
				sx[++cnt2]=i;
				sy[cnt2]=j;
			}
		}
	}
	for(int i=1;i<=cnt1;i++){
		for(int j=1;j<=cnt2;j++){
			e[++cnt].u=i;
			e[cnt].v=j;
			e[cnt].dis=sqrt((sx[j]-px[i])*(sx[j]-px[i])+(sy[j]-py[i])*(sy[j]-py[i]));
		}
	} 
	sort(e+1,e+cnt+1,cmp);
	for(int i=1;i<=cnt;i++){
		int u=e[i].u,v=e[i].v;
		if(vis[u]){
			continue;
		}
		if(!zhan[v]){
			vis[u]=v;
			zhan[v]=u;
			sum[v]++;
		}
		else{
			double dis=e[i].dis;
			double dis1=sqrt((sx[v]-px[zhan[v]])*(sx[v]-px[zhan[v]])+(sy[v]-py[zhan[v]])*(sy[v]-py[zhan[v]]));
			if(dis==dis1){
				zhan[v]=u;
				vis[u]=v;
				sum[v]++;
			}
		}
	}
	int ans=0;
	for(int i=1;i<=cnt2;i++){
		if(sum[i]>1)ans++;
	}
	cout<<ans;
	return 0;
}
posted @   Weslie_qwq  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示