• Codeforces 698D Limak and Shooting Points (搜索)


    题目链接

    https://codeforces.com/contest/698/problem/D

    题解

    玄妙好题啊
    对于每个元素(j)判断(j)是否可被射中。假设我们要用第(i)个弓箭射中第(j)个目标,那么在射中之前有若干个目标是我们需要先射中的。但我们并不知道应该用哪些目标射中。
    于是我们可以枚举一个(1)(m)的全排列(P_k), 然后进行BFS. 初始队列中只有(j),每次取出队首元素(设队首在队列中的位置为(k)),然后用(P_k)去射队首元素,然后加入队列。若队列中元素个数超过(m), 则无解(以这个顺序射中(j)是不可能的)。
    时间复杂度(O(k!kn))

    代码

    #include<bits/stdc++.h>
    #define llong long long
    #define mkpr make_pair
    #define riterator reverse_iterator
    using namespace std;
    
    inline int read()
    {
    	int x = 0,f = 1; char ch = getchar();
    	for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
    	for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
    	return x*f;
    }
    
    const int N = 1000;
    const int M = 7;
    struct Point
    {
    	int x,y;
    } a[M+2],b[N+3];
    vector<int> l[M+2][N+3];
    int permu[M+2];
    int que[N+3]; bool vis[N+3];
    int n,m;
    
    int main()
    {
    	scanf("%d%d",&m,&n);
    	for(int i=1; i<=m; 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);
    	for(int i=1; i<=m; i++)
    	{
    		for(int j=1; j<=n; j++)
    		{
    			for(int k=1; k<=n; k++) if(k!=j)
    			{
    				if(1ll*(b[j].x-a[i].x)*(b[k].y-a[i].y)==1ll*(b[j].y-a[i].y)*(b[k].x-a[i].x) && (1ll*(a[i].x-b[k].x)*(b[j].x-b[k].x)<0 || (a[i].x==b[k].x&&1ll*(a[i].y-b[k].y)*(b[j].y-b[k].y)<0)))
    				{
    					l[i][j].push_back(k);
    				}
    			}
    		}
    	}
    	int fans = 0;
    	for(int j=1; j<=n; j++)
    	{
    		for(int i=1; i<=m; i++) permu[i] = i;
    		bool ans = false;
    		do
    		{
    			for(int i=1; i<=n; i++) vis[i] = false;
    			bool cur = true;
    			int hd = 1,tl = 1; que[tl] = j; vis[j] = true;
    			while(hd<=tl)
    			{
    				int u = que[hd];
    				for(int i=0; i<l[permu[hd]][u].size(); i++)
    				{
    					if(vis[l[permu[hd]][u][i]]) continue;
    					que[++tl] = l[permu[hd]][u][i]; vis[l[permu[hd]][u][i]] = true;
    					if(tl>m) {cur = false; break;}
    				}
    				if(!cur) {break;}
    				hd++;
    			}
    			if(cur) {ans = true; break;}
    		} while(next_permutation(permu+1,permu+m+1));
    		if(ans) {fans++;}
    	}
    	printf("%d
    ",fans);
    	return 0;
    }
    
  • 相关阅读:
    使用Eolinker拓展API设计
    如何记录API
    API设计
    【翻译】通过API主导的集成来证明您的业务未来
    从状态库迁移分布系统建设方式
    PostgreSql 查询某个模式下面的所有表
    迁移状态库的地市区县信息
    测开和开发的难度对比
    yum源的三种搭建方式
    Harbor实现容器镜像仓库的管理和运维
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12348088.html
Copyright © 2020-2023  润新知