zoukankan      html  css  js  c++  java
  • 洛谷 P2831 [NOIP2016]愤怒的小鸟

    传送

    一些废话

    题太难了,于是这次不写解析,具体思路可以看这位聚聚的博客:

    聚聚的博客

    这里说对搜索题的一点看法。

    首先是实数域上的搜索。对于本题而言,显然抛物线的每个参数都是实数,断绝了一般枚举的可能。对于这类情况,常用的转化是:

    枚举所有的情况 -> 枚举可能的情况
    

    对于本题,具体而言,显然绝大部分抛物线都是无用的,而两只猪的坐标可以确定一条过原点的抛物线(当然,别忘了排除不合法的情况),所以我们枚举所有这样的猪对即可。

    与本题类似地,有 (uva303) ,如果有兴趣可以去看一眼。

    其次,每条抛物线可能击杀多只猪,但每次都去判断是否击杀某只猪过于奢侈,于是我们对每条抛物线就算一次,把能击杀的猪用二进制数存起来。这也是一个常用的优化策略避免赘余运算

    以上。

    参考程序

    #include<iostream>
    #include<vector>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int n,m,t,bin[20][20],mem[1<<18];
    const double eps = 1e-7;
    const int inf = 0x3f3f3f3f;
    struct pig{
    	double x,y;
    }p[20];
    inline double calca(pig i,pig j){
    	return (j.x * i.y - i.x * j.y)
    	 / (i.x * j.x * (i.x - j.x));
    }
    inline double calcb(pig i,pig j){
    	return (i.x * i.x * j.y - j.x * j.x * i.y)
    	 / (i.x * j.x * (i.x - j.x));
    }
    void calc(double a,double b){
    	vector<int> kill;
    	int state = 0;
    	for(int i = 0;i < n;i++)
    		if(fabs(a * p[i].x * p[i].x + b * p[i].x - p[i].y) < eps){
    			state |= (1<<i);
    			kill.push_back(i);
    		}
    	for(int i = 0;i < kill.size();i++)
    		for(int j = i + 1;j < kill.size();j++)
    			bin[kill[i]][kill[j]] = bin[kill[j]][kill[i]] = state;
    }
    int dfs(int state){
    	if(mem[state] != -1) return mem[state];
    	mem[state] = inf;
    	for(int i = 0;i < n;i++){
    		if(state & (1<<i)) continue;
    		bool flag = 0;
    		for(int j = 0;j < n;j++)
    			if((state & (1<<j)) == 0 && p[i].x != p[j].x && calca(p[i],p[j]) < 0.0){
    				flag = 1;
    				if(bin[i][j] == -1) calc(calca(p[i],p[j]),calcb(p[i],p[j]));
    				mem[state] = min(mem[state],dfs(state | bin[i][j]) + 1);
    			}
    		if(!flag) return mem[state] = dfs(state | (1<<i)) + 1;
    	}
    	return mem[state];
    	
    }
    int main(){
    	cin >> t;
    	while(t--){
    		cin >> n >> m;
    		for(int i = 0;i < n;i++)
    			cin >> p[i].x >> p[i].y;
    		memset(bin,-1,sizeof(bin));
    		memset(mem,-1,sizeof(mem));
    		mem[(1<<n)-1] = 0;
    		cout << dfs(0) << endl;
    	}
    	return 0;
    } 
    
  • 相关阅读:
    js定义一个处理字符串的函数
    linux设置别名
    php对图片加水印--将图片先缩小,再在上面加水印
    php对图片加水印--将文字作为水印加到图片
    虚拟机非正常关闭,里面的服务器重启报错:Error, some other host already uses address
    php对图片加水印--将一张图片作为水印加到另一张图片
    Fatal error: Call-time pass-by-reference has been removed in *****.php on line 18
    php中array_walk() 和 array_map()两个函数区别
    nginx 代理转发 wcf接口
    js 日期格式化
  • 原文地址:https://www.cnblogs.com/mysterious-garden/p/9884994.html
Copyright © 2011-2022 走看看