愤怒的小鸟

这道题:
用一个二维数组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)

  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 }
View Code

 

posted @ 2017-07-28 06:02  A_LEAF  阅读(245)  评论(0编辑  收藏  举报