三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

洛谷P1378 油滴扩展

洛谷P1378 油滴扩展

题目

传送门

见解

我发现在一定难度上的题目,例如这道题目,他都具有一定的思维转换能力。你一开始看他很难,实际上主要读懂了它你就会做了,因为他的编码难度真的不高

题目大意

给你四个坐标,分别是一个长方形两个对角的坐标,然后再给你N个点,让你在这N个点上放一个可以扩散的油滴,这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。问要按照什么样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总面积最大呢?

思路

大体

枚举也就是DFS每个顺序,然后和我们最后的答案ans比较大小即可。

细节

难度在于怎么样确定每个圆的半径,以及判断他是否合法。这里我们可以用chenk函数来解决

chenk函数

定义一个sr变量来确定这个点的半径,在他与x和y边界的距离里取最小值然后遍历已经确定的点的半径与这个点的距离,取最小值。如果一旦距离小于0,那么就去取0.

收尾

利用求出来的矩形面积减去ans再加上0.5即可得到答案长方形盒子剩余的最小空间!!!

代码

#include<bits/stdc++.h>
using namespace std;
int n;
bool vis[9];
double r[9];
double x,y,xx,yy;
struct u{double x,y;
}a[8];
double ans=0.0;
double check(int s){double s1=min(abs(a[s].x-xx),abs(a[s].x-x));double s2=min(abs(a[s].y-yy),abs(a[s].y-y));double sr=min(s1,s2);//再它与x,y两个边界的距离里求最小值 for(int i=1;i<=n;i++){if(vis[i]==true&&i!=s){//遍历每个确定的点并且不等于正在求的这个点 double	t=sqrt((a[i].x-a[s].x)*(a[i].x-a[s].x)+(a[i].y-a[s].y)*(a[i].y-a[s].y));//勾股定理来确定距离 sr=min(sr,max(0.0,t-r[i]));//减去确定的点的半径来确定我们要求的点的半径,如果小于0就取0 }}return sr; 
}
void dfs(int s,double sum){if(s>n){ans=max(ans,sum);//n个点都放了 return;//回溯 }for(int i=1;i<=n;i++){if(vis[i]==false){//如果没确定 vis[i]=true;//标记 r[i]=check(i);//求半径 dfs(s+1,sum+3.1415926535*r[i]*r[i]);vis[i]=false;//还原 }}
} 
int main(){cin>>n;cin>>x>>y>>xx>>yy;for(int i=1;i<=n;i++){cin>>a[i].x>>a[i].y;}dfs(1,0);double t=abs(x-xx)*abs(y-yy);//长方形的面积 cout<<int(t-ans+0.5);//四舍五入 return 0;
} 
← 返回列表