zoukankan      html  css  js  c++  java
  • 题解 P2831 【愤怒的小鸟】

    题目链接

    Solution 愤怒的小鸟

    题目大意:第一象限内有(n)个点((n leq 18)),求最少要多少条形如(y=ax^2+bx quad a<0,a,b, in R) 的抛物线才能覆盖所有点

    状压(dp)


    分析:(n)的数据范围很小,因此我们可以考虑状压(dp),填表法不好做我们可以用刷表法

    (f[S])表示覆盖集合(S)内点的最小代价

    显然(f[0]= 0)

    (f[S|line[i][j]] = min{f[S] + 1})其中(line[i][j])表示经过(i,j)两点的抛物线可以覆盖的点的集合

    (f[S | 1<<i] = min{f[S] + 1})

    这样单次复杂度(O(2^nn^2)),有点悬

    状态的(2^n)不能消掉我们从转移入手

    原来每次枚举所有没有被覆盖的点是(n^2)的,我们固定其中一个点为没有被覆盖的点中编号最小的,这样转移就是(n)

    为什么这样是对的?因为我们最终要求的是覆盖所有的点,当前状态不覆盖最小的点也会被下一个状态覆盖,所以可以直接钦定一个点

    这题样例都卡精度,醉了

    #include <algorithm>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int maxn = 23;
    typedef long double type;
    const type eps = 1e-7;
    struct Pos{
    	type x,y;
    }val[maxn];
    int t,n,m,dp[1 << maxn],lowbit[1 << maxn],line[maxn][maxn];//lowbit表示最小的为0的点的编号
    inline bool cmp(type a,type b){return abs(a - b) < eps;}
    void gauss(type &x,type &y,type a1,type b1,type c1,type a2,type b2,type c2){
    	x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1);
    	y = (c1 - a1 * x) / b1;
    }
    inline void solve(){
    	cin >> n >> m;
    	for(int i = 0;i < n;i++)
    		cin >> val[i].x >> val[i].y;
    	memset(line,0,sizeof(line));
    	memset(dp,0x3f,sizeof(dp));
    	dp[0] = 0;
    	for(int i = 0;i < n;i++)
    		for(int j = 0;j < n;j++){
    			if(cmp(val[i].x,val[j].x))continue;
    			type a,b;
    			gauss(a,b,val[i].x * val[i].x,val[i].x,val[i].y,val[j].x * val[j].x,val[j].x,val[j].y);
    			if(a > -eps)continue;
    			for(int k = 0;k < n;k++)
    				if(cmp(a * val[k].x * val[k].x + b * val[k].x,val[k].y))line[i][j] |= 1 << k;
    		}
    	for(int i = 0;i < 1 << n;i++){
    		int j = lowbit[i];
    		dp[i | (1 << j)] = min(dp[i | (1 << j)],dp[i] + 1);
    		for(int k = 0;k < n;k++)
    			dp[i | line[j][k]] = min(dp[i | line[j][k]],dp[i] + 1);
    	}
    	cout << dp[(1 << n) - 1] << '
    ';
    }
    int main(){
    	for(int i = 0;i < (1 << 18);i++){
    		int j = 0;
    		for(;(i >> j) & 1;j++);
    		lowbit[i] = j;
    	}
    	cin >> t;
    	while(t--)solve();
    	return 0;
    }
    
  • 相关阅读:
    Ubuntu 12.04 LTS 及ubuntu14.10 -- NFS安装
    AutoFac文档4(转载)
    能粘贴Word 内容(含公式)的在线编辑器
    能粘贴Word 内容(含图片)的在线编辑器
    js+SpringBoot分片上传大文件
    js+SpringMVC分片上传大文件
    js+vue分片上传大文件
    js+csharp分片上传大文件
    js+c#.net分片上传大文件
    js+c#分片上传大文件
  • 原文地址:https://www.cnblogs.com/colazcy/p/11711571.html
Copyright © 2011-2022 走看看