NOIP 2016 Day2 T3 愤怒的小鸟

来源:互联网 发布:懒人淘宝商城 编辑:程序博客网 时间:2024/05/17 06:18
//状压DP,(1<<n)-1相当于全集。 #include<bits/stdc++.h>using namespace std;const int inf = 0x3f3f3f3f;const double lit = 1e-6;int t, n, m;double a, b;int f[1048576], c[22][22];struct node{    double x, y;    bool operator < (const node& r) const {        if(x == r.x)    return y < r.y;        return x < r.x;    }} mp[22];inline bool same(double p, double q){    return fabs(p - q) < lit;}inline void getInit(){    memset(c, 0, sizeof(c));    int nn = n/3+2;    /*if(m == 1)        for(int i = 0; i <= (1<<n); i++)            f[i] = nn;    else */    for(int i = 0; i <= (1<<n)-1; i++)        f[i] = inf;}int main(){    scanf("%d", &t);    while(t--){        scanf("%d%d", &n, &m);        getInit();        for(int i = 1; i <= n; i++)            scanf("%lf%lf", &mp[i].x, &mp[i].y);        //sort(mp+1, mp+n+1);        for(int i = 1; i < n; i++)            for(int j = i+1; j <= n; j++){//预处理两猪间的抛物线,并记录这条抛物线上所有的点                 double xi = mp[i].x, yi = mp[i].y;                double xj = mp[j].x, yj = mp[j].y;                if(same(xi, xj))    continue;                a = (yi/xi-yj/xj) / (xi-xj);                if(a >= 0)  continue;                b = yi/xi - a*xi;                for(int k = 1; k <= n; k++){                    double xk = mp[k].x, yk = mp[k].y;                    if(same(a*xk+b, yk/xk)) c[i][j] |= (1<<(k-1));                }            }        f[0] = 0;        for(int i = 0; i <= (1<<n)-1; i++)            for(int j = 1; j <= n; j++){                if(!(i & (1<<(j-1)))){                    for(int k = j; k <= n; k++){                        if(j == k)  f[i|(1<<(j-1))] = min(f[i]+1, f[i|(1<<(j-1))]);//DP不一定只改变当前状态,还可根据当前状态转移。                         if(same(mp[j].x, mp[k].x))  continue;                        f[i|c[j][k]] = min(f[i]+1, f[i|c[j][k]]);                    }                    break;//如果转移了第n(n>1)的猪,那第一头回来还是要专一,所以转移第一头即可。                 }            }        printf("%d\n", f[(1<<n)-1]);    }    return 0;}
原创粉丝点击