标签:int double 状压 pos 小鸟 xx 抛物线 path DP
题目描述
给定\(N\)个点,和形式抛物线\(y = ax^2 + bx\),每次可以消去抛物线上的点,问消去所有点的最少抛物线数时是多少?
范围
\(N \leq 18\)
题解
题目相当于dancing links
思想,用\(n^2\)个抛物线去覆盖点集,那么设\(f_i\)表示覆盖了第\(i\)列的最少行数是多少,转移:
\(f_{i|j} = min(f_i + 1,f_{i|j})\)
预处理经过任意两点的抛物线所覆盖集合即可。
复杂度\(O(T(n^3 + n2^n))\)
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 18;
const double eps = 1e-8;
struct node {
double x,y;
}pos[N];
int cmp(double x,double y) {
if(fabs(x - y) < eps) return 0;
if(x < y) return -1;
return 1;
}
int n,m;
int path[N][N];
int f[1 << N];
int main () {
int T;
cin >> T;
while(T --) {
cin >> n >> m;
for(int i = 0;i < n; ++i) {
cin >> pos[i].x >> pos[i].y;
}
memset(path,0,sizeof path);
for(int i = 0; i < n; ++i) {
path[i][i] = 1 << i;
for(int j = 0;j < n; ++j) {
double x1 = pos[i].x;
double x2 = pos[j].x;
double y1 = pos[i].y;
double y2 = pos[j].y;
if(!cmp(x1,x2)) continue;
double a = (y1 / x1 - y2 / x2) / (x1 - x2);
double b = y1 / x1 - a * x1;
if(cmp(a,0) >= 0) continue;
int sta = 0;
for(int k = 0;k < n; ++k) {
double xx = pos[k].x;
double yy = pos[k].y;
if(!cmp(a * xx * xx + b * xx,yy)) {
sta += 1 << k;
}
}
path[i][j] = sta;
}
}
memset(f,0x3f,sizeof f);
f[0] = 0;
for (int i = 0;i < (1 << n) - 1; ++i) {
int tmp = 0;
for(int j = 0;j < n; ++j) {
if(!(i >> j & 1)) {
tmp = j;
break;
}
}
for(int j = 0;j < n; ++j) {
f[i | path[tmp][j]] = min(f[i] + 1,f[i | path[tmp][j]]);
}
}
cout << f[(1 << n) - 1] << endl;
}
return 0;
}
标签:int,double,状压,pos,小鸟,xx,抛物线,path,DP 来源: https://www.cnblogs.com/akoasm/p/15169062.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。