P1378
油滴扩展
题目描述
在一个长方形框子里,最多有 \(N\) 个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这 \(N\) 个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式 \(V = \pi r^2\),其中 \(r\) 为圆的半径。
输入格式
第一行,一个整数 \(N\)。
第二行,四个整数 \(x, y, x', y'\),表示长方形边框一个顶点及其对角顶点的坐标。
接下来 \(N\) 行,第 \(i\) 行两个整数 \(x_i, y_i\),表示盒子内第 \(i\) 个点的坐标。
输出格式
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)。
样例 #1
样例输入 #1
2
20 0 10 10
13 3
17 7
样例输出 #1
50
提示
对于 \(100\%\) 的数据,\(1 \le N \le 6\),坐标范围在 \([-1000, 1000]\) 内。
很好的一道搜索题 细节比较多
开始只有60pts 原因是因为:
!!!只用考虑滴了油滴的点与目前点的距离 没有滴过的不用管!!!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,sx,sy,tx,ty;
int x[10],y[10];
double r[10];
double dis[10][10],maxx;
const double pi=acos(-1);
int vis[10];
void dfs(int step,double tot,int cnt)
{
// cout<<cnt<<": "<<step<<" "<<tot<<" ";
if(cnt==n+1)
{
return ;
}
double minn=INT_MAX;
minn=min(minn,(double)(abs(x[step]-sx)));
minn=min(minn,(double)(abs(-x[step]+tx)));
minn=min(minn,(double)(abs(y[step]-sy)));
minn=min(minn,(double)(abs(-y[step]+ty)));
// cout<<minn<<" ";
for(int i=1;i<=n;i++)
{
if(i==step)continue;
if(!vis[i])continue;//!!!!!!!!
if(dis[i][step]<r[i]-1e-6)
{
minn=0;
break;
}
minn=min(minn,abs(dis[i][step]-r[i]));
}
// cout<<minn<<"\n";
r[step]=minn;
vis[step]=1;
maxx=max(maxx,tot+pi*minn*minn);
for(int i=1;i<=n;i++)
{
if(!vis[i])
dfs(i,tot+pi*minn*minn,cnt+1);
}
r[step]=0;
vis[step]=0;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
cin>>sx>>sy>>tx>>ty;
// sx+=1001,sy+=1001,tx+=1001,ty+=1001;
for(int i=1;i<=n;i++)
cin>>x[i]>>y[i];//x[i]+=1001,y[i]+=1001;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// cout<<dis[i][j]<<" ";
// cout<<"\n";
// }
for(int i=1;i<=n;i++)
{
memset(r,0,sizeof(r));
memset(vis,0,sizeof(vis));
dfs(i,0.0,1);
}
printf("%.0lf\n",(double)(abs(tx-sx)*abs(ty-sy))-maxx);
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号