To_Heart—题解——CF1209F

题目链接

link.

题解

可以发现,如果每一条边的编号位数相同就会很好处理,又可以发现走过一条编号为 1 的边和一条编号为 2 的边的贡献与走过一条编号为 12 的边相等,所以我们考虑拆边,将边按照十进制进行拆分。因为每条边只有一位了,所以最短的距离肯定走最少的边,所以我们把问题转换成了最短路问题。

然后因为如果存在多条出边,我们要走权最小的那条边,所以可以将出边进行 0~9 分类。

然还有一个问题,上文提到过走 1 再走 2 和走 12 是等价的,但如果出现下图的情况:在这里插入图片描述
s s s 出发,我们有可能会选择走 1->2->3->4 的道路到达 t t t ,但显然这不是最近的道路。

为了避免这种情况,我们需要在每次搜索时让层数相同的一起扩展。

但还有一个问题:在这里插入图片描述
如图,将第三层的放在一起扩展,但可能会出现 2 < 3 2< 3 2<3 ,所以我先从下面扩展的终点的情况。所以其实我们扩展并不是将同一层的放一起,而是将目前为止价值相同的按照下一条边的权值从小到大进行扩展。

code

#include<bits/stdc++.h>
using namespace std;
#define db double

int n,k,ans=0;
struct zz{
	int x,y;	
}a[15],b[1005];
vector<int> v[15][1005];
bool cmp(zz x,zz y){
	if(x.x==y.x) return x.y<y.y;
	return x.x<y.x; 
}

bool Cheak(zz x,zz y,zz yy){
	if(x.x==y.x&&x.x==yy.x) return 1;
	if(x.x==y.x&&x.x==yy.x) return 1;
	return (x.y-y.y)*(x.x-yy.x)==(x.y-yy.y)*(x.x-y.x);
}

void Fk(){
	for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) for(int l=1;l<=n;l++) if(j!=l&&Cheak(a[i],b[j],b[l]))
		if(min(a[i].x,b[j].x)<=b[l].x&&b[l].x<=max(a[i].x,b[j].x)&&min(a[i].y,b[j].y)<=b[l].y&&b[l].y<=max(a[i].y,b[j].y)) 
			v[i][j].push_back(l);
}

bool f[15];
int t[15],sum=0;
bool vis[1005];


bool DFS(int x){
	if(sum==k+1) return 0;
	int now=t[sum++];
	for(auto y:v[now][x]) if(!vis[y]&&!DFS(y)) return 0;
	vis[x]=1;
	return 1;
}

bool Check(int x,int tot){
	if(tot==k+1){ memset(vis,0,sizeof vis);sum=1;return DFS(x); }
	for(int i=1;i<=k;i++) if(!f[i]){
		f[i]=1;t[tot]=i;
		if(Check(x,tot+1)) return 1;
		f[i]=0;
	}
	return 0;
}

int main(){
	cin>>k>>n;
	for(int i=1;i<=k;i++) scanf("%d%d",&a[i].x,&a[i].y);
	for(int i=1;i<=n;i++) scanf("%d%d",&b[i].x,&b[i].y);
	Fk();
	for(int i=1;i<=n;i++){
		ans+=Check(i,1);
		memset(f,0,sizeof f);
	}
	cout<<ans<<endl;
	return 0;
}
```









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值