愤怒的小鸟
这道题: 用一个二维数组g[i][j]记录经过两个猪的抛物线还能经过那几个猪 f[]全都初始化成无穷大 f[i]=minn(f[i&(~g[j][k])+1); 这个应该都知道了 值得注意的是: 1.精度0.000001 2.有横坐标相同的猪: 处理的时候可以把他两的a直接置为正数, dp就判断一下a>=0 continue; 3.有原点和两个猪在同一条直线(过原点的直线)上的猪 (y1/x1)-(y2/x2)<=0.000001; 4.有坐标完全相同的猪(虽说题目上说没有) 预处理的时候去重 O(2^n*n*n) 优化: 一句话:既然这个状态的所有猪都要被打掉, 为什么不现在打? 意思就是: 不用再枚举n*n条抛物线 只要枚举其中一只猪所在的抛物线就可以了 比如: 有三只猪(x1,y1),(x2,y2),(x3,y3) 过1,2猪的抛物线过3 哪过2,3的抛物线也过1 所以只需枚举一条即可 然后就变成了O(2^n*n)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define mem(a,b) memset(a,b,sizeof(a)) 6 using namespace std; 7 const double qqq=0.000004; 8 const int N=(1<<18)+10; 9 10 inline int minn(int a,int b) 11 { 12 return a<b?a:b; 13 } 14 15 inline int lowbit(int x) 16 { 17 return x&(-x); 18 } 19 20 inline double abss(double x) 21 { 22 if(x<0) 23 return -x; 24 return x; 25 } 26 27 int fin(int x) 28 { 29 int temp=lowbit(x); 30 int k=1; 31 while(1) 32 { 33 if((1<<(k-1))==temp) 34 return k; 35 ++k; 36 } 37 } 38 39 struct son 40 { 41 double x,y; 42 }; 43 son q[101]; 44 45 bool ok(son a,son b) 46 { 47 return a.x<b.x; 48 } 49 50 int t,n,m; 51 double a[21][21],b[21][21]; 52 int g[21][21]; 53 int f[N]; 54 double o,p; 55 int maxp; 56 int now; 57 58 void chu() 59 { 60 now=0; 61 mem(a,0); 62 mem(b,0); 63 mem(g,0); 64 mem(f,0x7f); 65 mem(q,0); 66 scanf("%d%d",&n,&m); 67 for(int i=1;i<=n;i++) 68 { 69 scanf("%lf%lf",&o,&p); 70 //cout<<o<<' '<<p<<endl; 71 int flag=0; 72 for(int j=1;j<=now;j++) 73 if(o==q[j].x&&p==q[j].y) 74 { 75 flag=1; 76 break; 77 } 78 if(flag==1) 79 continue; 80 q[++now].x=o; 81 q[now].y=p; 82 } 83 n=now; 84 maxp=(1<<n)-1; 85 sort(q+1,q+1+n,ok); 86 for(int i=1;i<=n;i++) 87 for(int j=1;j<=n;j++) 88 { 89 if(i==j) 90 { 91 a[i][j]=-1; 92 continue; 93 } 94 double x1=q[i].x,x2=q[j].x,y1=q[i].y,y2=q[j].y; 95 if(x1==x2) 96 { 97 a[i][j]=1; 98 continue; 99 } 100 if(abss(y1/x1-y2/x2)<=qqq) 101 { 102 a[i][j]=1; 103 b[i][j]=1; 104 continue; 105 } 106 a[i][j]=(x1*y2-x2*y1)/(x2*x2*x1-x2*x1*x1); 107 b[i][j]=(y1/x1)-(x1*y2-x2*y1)/(x2*x2-x2*x1); 108 } 109 110 for(int i=1;i<=n;i++) 111 for(int j=1;j<=n;j++) 112 { 113 if(q[i].x==q[j].x) 114 { 115 g[i][j]=g[i][j]|(1<<(i-1)); 116 g[i][j]=g[i][j]|(1<<(j-1)); 117 continue; 118 } 119 if(i==j) 120 { 121 g[i][j]=g[i][j]|(1<<(i-1)); 122 continue; 123 } 124 g[i][j]=g[i][j]|(1<<(i-1)); 125 g[i][j]=g[i][j]|(1<<(j-1)); 126 for(int k=1;k<=n;k++) 127 { 128 if(k==i||k==j) 129 continue; 130 if(q[k].x==q[i].x||q[k].x==q[j].x) 131 continue; 132 if(a[i][j]>=0) 133 continue; 134 double temp=a[i][j]*q[k].x*q[k].x+b[i][j]*q[k].x; 135 double temp1=abss(q[k].y-temp); 136 if(temp1<=qqq) 137 { 138 g[i][j]=g[i][j]|(1<<(k-1)); 139 //cout<<"a[i][j]="<<a[i][j]<<' '; 140 //cout<<"i="<<i<<" j="<<j<<" k="<<k<<" temp="<<temp<<" y[k]="<<q[k].y<<endl; 141 } 142 } 143 } 144 } 145 146 void work() 147 { 148 f[0]=0; 149 for(int i=1;i<=maxp;i++) 150 { 151 int temp=fin(i); 152 for(int j=1;j<=n;j++) 153 { 154 if(a[temp][j]>=0) 155 { 156 f[i]=minn(f[i],f[i&(~g[temp][j])]+2); 157 continue; 158 } 159 f[i]=minn(f[i&(~g[temp][j])]+1,f[i]); 160 //cout<<"i="<<i<<" f[i]="<<f[i]<<endl; 161 } 162 } 163 printf("%d\n",f[maxp]); 164 } 165 166 167 168 int main(){ 169 //freopen("2.txt","w",stdout); 170 //freopen("angrybirds.in","r",stdin); 171 //freopen("angrybirds.out","w",stdout); 172 scanf("%d",&t); 173 while(t--) 174 { 175 chu(); 176 work(); 177 } 178 179 180 181 //while(1); 182 return 0; 183 }