Angry Birds with Size Pressure dp--NOIP2016

There are n points (xi; yi) in the first quadrant of a plane, and you can specify any one for each operation
A; B (a < 0) and eliminate the points on parabola y = ax2 + bx to find the minimum number of operations
Eliminate all points
n<=18

solution:
Solution 1:
f[S] represents the minimum number of times required to eliminate points in set S
You can enumerate two points that are not in S to get a parabola at a time, and then calculate all the points that the parabola can eliminate
If the new set is S', after adding the point eliminated by this parabola, then f[S] + 1 is used to update f[S', time complexity O(n^2 * 2^n)
Notice that the final result must eliminate all points, so you might want to eliminate the lowest zero by default each time, so you only need to enumerate one point, time complexity O(n*2^n)

This is the solution explained by gwy, which has a default step of eliminating the lowest zero every time to reduce complexity.
Is also a regular operation

Solution 2:
Because three points determine a parabola
So you might want to enumerate two pigs to calculate a and b at this time*
Enumerate the other pigs to see which pigs this bird can kill without this parabola and record with a bir array**
Remember to judge if x is the same as a<0
There's also a case where n=1 needs to be judged
Then do dp, enumerate the birds this time and the last collection, take min to transfer
Time Complexity O(n^3+n*2^n)

It seems like I heard a little bit about it a long time ago.. Then I thought it would be convenient for qwq to do so

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 20
using namespace std;
int t,n,m,bir[maxn*maxn],dp[1<<maxn],tot;
double px[maxn],py[maxn];
const double eps=1e-6;
bool vis[maxn];

void init(){
  memset(bir,0,sizeof bir); memset(dp,0x3f,sizeof dp); tot=0;
  memset(vis,0,sizeof vis);
}

int main(){
  scanf("%d",&t);
  while(t--){
    init();
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
      scanf("%lf%lf",&px[i],&py[i]);
    }
    if(n==1) {printf("1\n");continue;} //Forget the special judgment wa once here.
    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++){
        if(px[i]==px[j]) {
          if(!vis[i]) bir[++tot]=1<<(i-1),vis[i]=1;
          if(!vis[j]) bir[++tot]=1<<(j-1),vis[j]=1;
          continue;
        }
        double b=(py[j]*px[i]*px[i]-py[i]*px[j]*px[j])/(px[j]*px[i]*px[i]-px[i]*px[j]*px[j]);
        double a=(py[i]*px[j]-py[j]*px[i])/(px[i]*px[i]*px[j]-px[j]*px[j]*px[i]);
        if(a>=0) {
          if(!vis[i]) bir[++tot]=1<<(i-1),vis[i]=1;
          if(!vis[j]) bir[++tot]=1<<(j-1),vis[j]=1;
          continue;
        }
        bir[++tot]=(1<<(i-1))|(1<<(j-1));
        for(int t=j+1;t<=n;t++){
          if(fabs(a*px[t]*px[t]+b*px[t]-py[t])<=eps) bir[tot]=bir[tot]|(1<<(t-1));
        }
      }
    dp[0]=0;
    for(int i=1;i<=tot;i++)
      for(int j=0;j<(1<<n);j++){
        if((j|bir[i])==j) continue;
        dp[j|bir[i]]=min(dp[j|bir[i]],dp[j]+1);
      }
    printf("%d\n",dp[(1<<n)-1]);
  }
  return 0;
}

Posted on Sat, 08 Feb 2020 11:41:16 -0500 by daggardan