//状压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;
}
NOIP 2016 Day2 T3 愤怒的小鸟
最新推荐文章于 2019-01-30 08:12:00 发布