码迷,mamicode.com
首页 > 其他好文 > 详细

[NOIp2016提高组]愤怒的小鸟

时间:2017-11-04 20:51:15      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:etc   tin   ble   extra   getc   log   while   记录   include   

题目大意:
  平面直角坐标系的第一象限有n(n<=18)个点,你可以每次给出一个形如y=ax^2+bx的函数把经过这条函数的点消掉,问消掉所有的点至少要多少函数?

思路:
  枚举每两个点对,可以唯一确定一条函数,再枚举第三个点,判断一下是否会经过这条函数。
  状态压缩一下记录每条函数能消掉那些点。
  然后就是一个简单的状压DP。
  一开始由于把fabs打成了abs,样例都过不去,调了半个下午。
  洛谷上随便A,UOJ上被Extra数据hack掉了,把eps从1e-7改成1e-10就A了。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<algorithm>
 5 inline int getint() {
 6     register char ch;
 7     while(!isdigit(ch=getchar()));
 8     register int x=ch^0;
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0);
10     return x;
11 }
12 const int N=18;
13 const double eps=1e-10;
14 struct Point {
15     double x,y;
16 };
17 Point p[N];
18 int sit[N*N],s;
19 int f[1<<N];
20 inline double pow(const double &x) {
21     return x*x;
22 }
23 int main() {
24     for(register int T=getint();T;T--) {
25         const int n=getint();getint();
26         for(register int i=0;i<n;i++) {
27             scanf("%lf%lf",&p[i].x,&p[i].y);
28         }
29         for(register int i=0;i<n;i++) {
30             sit[i]=1<<i;
31         }
32         s=n;
33         for(register int i=0;i<n;i++) {
34             for(register int j=i+1;j<n;j++) {
35                 const double x1=p[i].x,x2=p[j].x,y1=p[i].y,y2=p[j].y;
36                 if(pow(x1)*x2==pow(x2)*x1) continue;
37                 const double a=(x2*y1/x1-y2)/(x1-x2)/x2,b=((pow(x2)*y1/pow(x1)-y2)/(pow(x2)/x1-x2));
38                 if(a>-eps) continue;
39                 sit[s]=(1<<i)|(1<<j);
40                 for(register int k=j+1;k<n;k++) {
41                     if(fabs(a*pow(p[k].x)+b*p[k].x-p[k].y)<eps) sit[s]|=1<<k;
42                 }
43                 s++;
44             }
45         }
46         for(register int i=1;i<(1<<n);i++) {
47             f[i]=1e9;
48         }
49         for(register int i=0;i<(1<<n);i++) {
50             for(register int j=0;j<s;j++) {
51                 f[i|sit[j]]=std::min(f[i|sit[j]],f[i]+1);
52             }
53         }
54         printf("%d\n",f[(1<<n)-1]);
55     }
56     return 0;
57 }

 

[NOIp2016提高组]愤怒的小鸟

标签:etc   tin   ble   extra   getc   log   while   记录   include   

原文地址:http://www.cnblogs.com/skylee03/p/7784131.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!