zoukankan      html  css  js  c++  java
  • LGOJP2831 愤怒的小鸟

    题目链接

    题目链接

    题解

    数据范围显然状压/爆搜。
    考虑(f[S])表示二进制下已打了的猪的集合。
    可以枚举(S)的子集(S_1),判定(S)(S_1)的补集(S_2)是否合法。
    判定可以通过待定系数法做到(O(n))判定。若补集合法,则(f[S]=min{f[S_1]+1 })
    复杂度是(O(Tn3^n))。这样能(70)分。
    考虑如何优化。因为(n)很小,所以可以(O(n^3))预处理出(g_{i,j})表示经过(i,j)两点的二次函数可达的点集。那么转移的时候枚举二次函数(通过枚举点(i)和点(j)),转移方程(f[S|g_{i,j}]=min{f[S]+1})
    那么复杂度降到(O(Tn^22^n))。已经可以通过本题了。
    唐神的(blog)里面还有个优化。
    一个结论:每个状态(S)用于转移的二次函数,一定经过该状态中不包含的第一个点(x)。因为最后的目标是选所有的点,这个点不选,在最后的最优方案中也一定会被其他点选到,而前面已经处理出了(g_{i,j}),可达点集已经都处理出来了。所以只用这个点(x)转移是合法的。
    如果预处理出来每个状态(S)所对应的(x)的话复杂度就是(O(Tn2^n))的。如果不处理的话会慢一点但也不会太多。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 20;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-10;
    int n, m, f[(1 << 18) + 5], T, g[N][N];
    double a[N], b[N];
    
    int main() {
    	scanf("%d", &T);
    	while(T--) {
    		scanf("%d%d", &n, &m);
    		for(int i = 0; i < n; ++i) scanf("%lf%lf", &a[i], &b[i]);
    		memset(g, 0, sizeof(g)); memset(f, 0x3f, sizeof(f)); f[0] = 0; 
    		for(int i = 0; i < n; ++i) {
    			for(int j = i + 1; j < n; ++j) {
    				if(a[i] == a[j]) continue;
    				double A = (b[i] - b[j] * a[i] / a[j]) / (a[i] * a[i] - a[i] * a[j]);
    				double B = (b[i] - A * a[i] * a[i]) / a[i];
    				if(A >= 0) continue;
    				for(int k = 0; k < n; ++k) 
    					if(fabs(b[k] - (A * a[k] * a[k] + B * a[k])) <= eps) g[i][j] |= 1 << k;
    			}
    		}
    		for(int S = 0; S < 1 << n; ++S) {
    			for(int i = 0; i < n; ++i) {
    				f[S | (1 << i)] = min(f[S | (1 << i)], f[S] + 1);
    				if(!(S & (1 << i))) {
    					for(int j = i + 1; j < n; ++j) 
    						f[S | g[i][j]] = min(f[S | g[i][j]], f[S] + 1);
    					break;
    				}
    			}
    		}
    		printf("%d
    ", f[(1 << n) - 1]);
    	}
    }
    
  • 相关阅读:
    使用rem来开发你的移动端网站
    在网页布局中合理使用inline formating context(IFC)
    构建OLAP CDP平台 Maven父子项目
    2014世界杯决赛观后感
    2013岁末总结
    11月11日上班杂谈
    这一年
    湖南联通发福利了C#为你月赚150M流量回家过年不再愁
    C# 实现对接电信交费易自动缴费 续(winio/winring0 自动填密码)
    C# 实现对接电信交费易自动缴费
  • 原文地址:https://www.cnblogs.com/henry-1202/p/11326488.html
Copyright © 2011-2022 走看看