【NOIp 2016】愤怒的小鸟

题目略

被奶会挂这题,然而并没有。。。

顺便吐槽一句:这题数据似乎有点水。。。O(n*2^n)最长才50ms。。。。。。

还有。。。m到底是干啥用的。。。全程没用上。。。

下面进入正题:

这道题还是蛮裸的,看一眼n<=182s,大概就猜到是O(n*2^n)了(然而后来发现时限是卖萌的)

直接状压不太优雅,而且萌新可能会搞不懂使用以前值的时间逻辑

所以,写递推好了:

d(S)=min(1+d(S'),d(S))

S'就是删去S中编号最小猪及其最多附属猪(可以一起打掉的)后的猪集合

记忆化一下,算d((1<<n)-1)就可以了

需要注意的几点是:

1.当P1,P2,O三点共线时,不可能构成抛物线

2.抛物线的a大于0时,不成立

3.可以单独打一个猪,要加个特判

下面上代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #define inf 0x3f3f3f3f
 4 #define eps 1e-6
 5 double sa[19][19],sb[19][19],px[19],py[19],x3,y3;
 6 int db[1<<19],n,d[1<<19];
 7 template<typename T>
 8 inline void read(T &x){
 9   char ch;while((ch=getchar()),(ch>'9'||ch<'0'));
10   x=ch-'0';while((ch=getchar()),(ch>='0'&&ch<='9')) x=x*10+ch-'0';
11 }
12 inline double abss(double x){
13     return x>=0?x:-x;
14 }
15 inline int minn(int a,int b){
16     return a<b?a:b;
17 }
18 inline bool mat(int i,int j,int k){
19     if(i==j&&j==k) return true;
20     x3=px[k],y3=py[k];
21     if(sa[i][j]!=0){
22         if(sa[i][j]>0) return false;
23         if(abss(x3*x3*sa[i][j]+x3*sb[i][j]-y3)<=eps) return true;
24         else return false;
25     }
26     sa[i][j]=sa[j][i]=(py[i]*px[j]-py[j]*px[i])/(px[i]*px[j]*(px[i]-px[j]));
27     sb[i][j]=sb[j][i]=py[i]/px[i]-(py[i]*px[j]-py[j]*px[i])/(px[j]*(px[i]-px[j]));
28     if(sa[i][j]>0) return false;
29     if(abss(x3*x3*sa[i][j]+x3*sb[i][j]-y3)<=eps) return true;
30     else return false;
31 }
32 int dp(int S){
33     if(d[S]<19) return d[S];
34     int i,j,k;
35     int ans;
36     for(i=1;i<=n;++i) if(S&(1<<(i-1))) break;
37     for(j=i;j<=n;++j)
38         if(((S&(1<<(j-1)))&&px[i]!=px[j]&&abss(py[j]/px[j]-py[i]/px[i])>eps)||i==j){
39             if(i==j){
40                 d[S]=minn(d[S],1+dp(S^(1<<(i-1))));
41                 continue;
42             }
43             ans=S;
44             for(k=i;k<=n;++k) if((S&(1<<(k-1)))&&mat(i,j,k)) ans^=(1<<(k-1));
45             if(ans!=S) d[S]=minn(1+dp(ans),d[S]);
46         }
47     return d[S];
48 }
49 int main(){
50     register int T,m;
51     read(T);
52     memset(db,inf,sizeof db);
53     db[0]=0;
54     for(register int b=0;b<19;++b) db[1<<b]=1;
55     for(register int a=0;a<T;++a){
56         memcpy(d,db,sizeof d);
57         read(n),read(m);
58         for(register int b=1;b<=n;++b) scanf("%lf%lf",&px[b],&py[b]);
59         printf("%d
",dp((1<<n)-1));
60         if(a==T-1) return 0;
61         memset(sa,0,sizeof sa);
62         memset(sb,0,sizeof sb);
63     }
64     return 0;
65 }
原文地址:https://www.cnblogs.com/lovely-lazy-tag-zly/p/7839068.html