标签:sharp scan pac logs tin ons register i+1 big

题目链接:uoj.ac/problem/265
一看到n<=18,其实就知道这是一道状压dp.
然后,我们就定义两个数组f[i][j]和dp[i].
f[i][j]表示以(0,0)(xi,yi)和(xj,yj)构成的抛物线最多可以射到几只猪的状态压成一个数,
1表示在抛物线上,0则反之,
那么先O(n3)暴力枚举一下就好了.
dp[i]表示完成状态为i的最优步数.
则dp[s|f[i][j]]=min(dp[s|f[i][j]],dp[s]+1).
O(2n)枚举状态s,
O(n2)进行状态转移,
所以总复杂度为O(2n*n2).
#include<iostream>
#include<cstdio>
#define BIG 1<<19
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
int n,m;
int T;
const double mimi=1e-10;
double x[21],y[21];
int f[21][21];
int dp[BIG];
inline double fabs(double a){
return a>=0?a:-a;
}
inline void deal(){
double a,b;
FOR(i,0,n-1)
FOR(j,0,n-1)
f[i][j]=0;
FOR(i,0,n-1)
f[i][i]=1<<i;
FOR(i,0,n-1)
FOR(j,i+1,n-1){
a=(x[i]*y[j]-x[j]*y[i])/(x[i]*x[j]*(x[j]-x[i]));
b=(y[j]*x[i]*x[i]-y[i]*x[j]*x[j])/((x[i]-x[j])*x[i]*x[j]);
if(a>=-mimi)
continue;
FOR(k,0,n-1)
if(fabs(a*x[k]*x[k]+b*x[k]-y[k])<=mimi)
f[i][j]|=(1<<k);
}
}
inline void solve(){
FOR(i,1,(1<<n))
dp[i]=2333;
FOR(s,0,(1<<n)-2)
FOR(i,0,n-1)
FOR(j,i,n-1)
dp[s|f[i][j]]=min(dp[s|f[i][j]],dp[s]+1);
cout<<dp[(1<<n)-1]<<endl;
return;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
FOR(i,0,n-1)
scanf("%lf%lf",&x[i],&y[i]);
deal();
solve();
}
return 0;
}
标签:sharp scan pac logs tin ons register i+1 big
原文地址:http://www.cnblogs.com/Stump/p/7674279.html