标签: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