思路:
考虑先求出经过 \((x_1,y_1),(x_2,y_2)\) 的抛物线解析式
我们有:
\[\begin{cases} ax_1^2 + bx_1 = y_1 \\ ax_2^2 + bx_2 = y_2\end{cases} \]
考虑将 \(b\) 消掉,求出 \(a\)。
那么考虑令 \(1\) 式减去 \(2\) 式的 \(\frac{x_1}{x_2}\) 倍:
\[ax_1^2 + bx_1 – ax_1x_2 – bx_1 = y_1 – \frac{x_1}{x_2} y_2 \]
\[a(x_1^2 -x_1x_2) = y_1 – \frac{x_1}{x_2} y_2 \]
\[a = \frac{y_1 – \frac{x_1}{x_2} y_2}{x_1^2 -x_1x_2} = \frac{y_1x_2 – x_1 y_2}{x_1^2x_2 – x_1x_2^2} \]
因为 \(a\) 太复杂度,不好带入,考虑也将 \(a\) 消掉,求出 \(b\)。
那么考虑令 \(1\) 式减去 \(2\) 式的 \(\frac{x_1^2}{x_2^2}\) 倍:
\[ax_1^2 + bx_1 – ax_1^2 – b\frac{x_1^2}{x_2} = y_1 – y_2 \frac{x_1^2}{x_2^2} \]
\[b(x_1 – \frac{x_1^2}{x_2}) = y_1 – y_2 \frac{x_1^2}{x_2^2} \]
\[b = \frac{y_1 – y_2 \frac{x_1^2}{x_2^2}}{x_1 – \frac{x_1^2}{x_2}} = \frac{y_1x_2^2 – y_2 x_1^2}{x_1x_2^2 – x_1^2 x_2} \]
那么我们可以得到经过 \((x_1,y_1),(x_2,y_2)\) 的抛物线解析式为:
\[y = \frac{y_1x_2 – x_1 y_2}{x_1^2x_2 – x_1x_2^2} x^2 + \frac{y_1x_2^2 – y_2 x_1^2}{x_1x_2^2 – x_1^2 x_2} x \]
可以通过这个解析式求出其它在这个抛物线上的点,设 \(A_{i,j}\) 表示经过点 \(i\) 和点 \(j\) 的抛物线经过的所有点的点集。
考虑状态压缩 dp,令 \(dp_S\) 表示 \(S\) 这个点集的鸟被射下来的最小次数,则:
\[dp_0 = 0 \]
\[dp_{S \operatorname{or} A_{i,j}} = \min(dp_{S \operatorname{or} A_{i,j}},dp_S + 1) \]
\[dp_{S \operatorname{or} 2^{i-1}} = \min(dp_{S \operatorname{or} 2^{i-1}},dp_S+1) \]
时间复杂度为 \(O(Tn^22^n)\)。
完整代码:
#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=19,M=(1ll<<N)+10;
const db Eps=1e-6;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
ll T,n;
ll a[N][N];
ll dp[M];
db x[N],y[N];
pair<db,db> get(db x1,db y1,db x2,db y2){
db a=(y1*x2-x1*y2)/(x1*x1*x2-x1*x2*x2);
db b=(y1*x2*x2-y2*x1*x1)/(x1*x2*x2-x1*x1*x2);
return {a,b};
}
db get(db x,db a,db b){
return a*x*x+b*x;
}
void solve(){
memset(dp,0x7f,sizeof(dp));
n=read(),read();
for(int i=1;i<=n;i++)
scanf("%lf%lf",&x[i],&y[i]);
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
a[i][j]=0;
auto t=get(x[i],y[i],x[j],y[j]);
if(t.fi>=0)
continue;
for(int k=1;k<=n;k++){
db h=get(x[k],t.fi,t.se);
if(abs(h-y[k])<=Eps)
a[i][j]|=(1ll<<(k-1));
}
}
}
dp[0]=0;
for(int S=0;S<(1ll<<n);S++){
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if((a[i][j]&S)==a[i][j])
continue;
dp[S|a[i][j]]=min(dp[S|a[i][j]],dp[S]+1);
}
}
for(int i=1;i<=n;i++)
dp[S|(1ll<<(i-1))]=min(dp[S|(1ll<<(i-1))],dp[S]+1);
}
write(dp[(1ll<<n)-1]);
putchar('\n');
}
bool End;
int main(){
T=read();
while(T--)
solve();
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容