zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    HDU3480-Division-斜率dp
    CDQ题目套路总结 [未完成]
    HDU5773-The All-purpose Zero-多校#41010-最长上升子序列问题
    POJ2763-Housewife Wind-树上单点修改区间求和
    HDU3507-Print Article-斜率dp入门题
    POJ2187-Beauty Contest-凸包
    SPOJ QTREE-Query on a tree-树链剖分-边权
    扫描系统进程和获取某进程的PID
    ConfuserEx壳
    关于Intel漏洞的学习
  • 原文地址:https://www.cnblogs.com/suncongbo/p/12348088.html
Copyright © 2011-2022 走看看