洛谷 P1378 油滴扩展
题目描述
在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)
注:圆的面积公式V=pi*r*r,其中r为圆的半径。
输入输出格式
输入格式:
第1行一个整数N。
第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。
接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。
以上所有的数据都在[-1000,1000]内。
输出格式:
一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)
输入输出样例
输入样例#1: 复制
2
20 0 10 10
13 3
17 7
输出样例#1: 复制
50
思路:一开始40分,后来改了好几次,没调出来,今天画了个图,就出来了。
所以最重要的还是数形结合。
错因:
if(sq<r[i]) R=0; R=min(R,sq-r[i]);
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 7 using namespace std; int n; double r[MAXN]; double pi=3.1415926535; int num[MAXN],vis[MAXN]; double ans=0x7f7f7f7f,x11,x22,y11,y22; struct nond{ double x,y; }v[MAXN]; double ab(double x){ return x>0?x:-x; } double work(int sum,double x,double y){ double R=min(ab(x-x11),min(ab(x-x22),min(ab(y-y11),ab(y-y22)))); for(int i=1;i<sum;i++){ double sq=sqrt((x-v[num[i]].x)*(x-v[num[i]].x)+(y-v[num[i]].y)*(y-v[num[i]].y)); if(sq<r[num[i]]) R=0; else R=min(R,sq-r[num[i]]); } return R; } void dfs(int tot,double sum){ if(tot==n+1){ if(sum<ans) ans=sum; return ; } for(int i=1;i<=n;i++) if(!vis[i]){ vis[i]=1;num[tot]=i; r[i]=work(tot,v[i].x,v[i].y); dfs(tot+1,sum-pi*r[i]*r[i]); vis[i]=0; } } int main(){ scanf("%d",&n); scanf("%lf%lf%lf%lf",&x11,&y11,&x22,&y22); for(int i=1;i<=n;i++) scanf("%lf%lf",&v[i].x,&v[i].y); dfs(1,ab(x11-x22)*ab(y11-y22)); printf("%.0lf",ans); } /* 3 -98 5 30 30 -42 11 -51 17 -11 22 2547 */
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。