NOIP2017 D2T3 题解

题面

这种数据范围不是乱搞dfs就是乱搞状压DP

首先应该通过任一方式求出a和b的值;

任意一条抛物线只用两头猪就可以确定,所以我们N^2枚举,并把在这两头猪的抛物线上的猪都存进状态state[i][j];

然后枚举任意两个还没消灭的小猪i,j;f[i|state[j][k]]=min(f[i|state[j][k]],f[i]+1);

因为有些小猪只能单独被消灭,所以:f[i|(1<<j-1)]=min(f[i|(1<<j-1)],f[i]+1);

然后就好了:

 

#include <bits/stdc++.h>
#define eps 1e-7
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
struct node{
	double x;
	double y;
}pig[20];
int f[1000010];
int bo[21];
int n,m;
int work(int pig1,int pig2)
{
	if(pig[pig1].x==pig[pig2].x) return 0;
	double x1=pig[pig1].x,x2=pig[pig2].x,y1=pig[pig1].y,y2=pig[pig2].y;
	double tmpx=x1*x1*x2-x2*x2*x1,tmpy=y1*x2-y2*x1;
	double a=tmpy/tmpx,b=(y1-a*x1*x1)/x1;
	if(a>=0) return 0;
	int res=0;  bo[pig1]=bo[pig2]=1;
	inc(i,1,n){
        double x=pig[i].x,y=pig[i].y;
        if(fabs(a*x*x+b*x-y)<eps) res|=1<<(i-1),f[1<<(i-1)]=f[res]=1;
    }
    return res;
}
int state[110][110];
int main()
{
	int t;
	cin>>t;
	while(t--){
		memset(f,0x3f,sizeof(f));
		memset(state,0,sizeof(state));
		memset(bo,0,sizeof(bo));
		scanf("%d%d",&n,&m);
		inc(i,1,n) scanf("%lf%lf",&pig[i].x,&pig[i].y),f[1<<i-1]=1;
		inc(i,1,n) inc(j,1,i-1) state[i][j]=work(i,j);
		inc(i,1,(1<<n)-1) inc(j,1,n){
			if((i>>j-1)&1==1)continue;
			inc(k,1,j-1){
               if(i&(1<<k-1)==1) continue;
               f[i|state[j][k]]=min(f[i|state[j][k]],f[i]+1);
            }
            f[i|(1<<j-1)]=min(f[i|(1<<j-1)],f[i]+1);
		}
		cout<<f[(1<<n)-1]<<endl;
	}
}

 

posted @ 2019-10-23 20:16  神之右大臣  阅读(255)  评论(0编辑  收藏  举报