Luogu P1378 油滴扩展
solution
这是一道很值得反思的题目
首先关于double的基本用法就非常不熟悉
- int + 0.0 = double int转化成double的方法
- printf 0.lf% 直接四舍五入输出int
关于题目其实并不是个很难的题目
关键就是搜索计算状态
就是比较得出r的过程 //特判一个r不用出来的答案直接当0计算
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 2147483647
#define pi 3.1415926535
int N,L,R;
int sx,sy,ex,ey;
bool vis[10];
double b[10],maxV=0.0;
struct Node{
int x,y;
}Dot[10];
double calR(double mx,double my,int i){
double tx=min(abs(mx-sx+0.0),abs(mx-ex+0.0));
double ty=min(abs(my-sy+0.0),abs(my-ey+0.0));
double r=min(tx,ty);
for(int k=1;k<=N;k++){
if(i!=k&&vis[k]){
double Dist=sqrt((mx-Dot[k].x)*(mx-Dot[k].x)+(my-Dot[k].y)*(my-Dot[k].y));
if(Dist-b[k]<=0)return 0; // 特判一个已经在里面的答案直接return0;
r=min(r,Dist-b[k]); // 不断优化当前r的答案
}
}
return r; // 返回当前情况的最优r
}
void dfs(double sum,int step){//搜索的本质就是穷竭枚举,所以不用考虑什么排序之类的东西
if(step==N){
if(sum>maxV)
maxV=sum;
return;
}
for(int i=1;i<=N;i++){
if(!vis[i]){
vis[i]=1;
b[i]=calR(Dot[i].x+0.0,Dot[i].y+0.0,i);//用b[i]记录对于i点当前的最有r答案
dfs(sum+pi*b[i]*b[i],step+1);
vis[i]=0;
b[i]=0.0;
}
}
}
int main(){
cin>>N;
cin>>sx>>sy>>ex>>ey;
L=abs(ex-sx),R=abs(ey-sy);
for(int i=1;i<=N;i++) cin>>Dot[i].x>>Dot[i].y;
dfs(0,0);
double Ans=L*R+0.0-maxV;
printf("%.0lf\n",Ans);
return 0;
}