Luogu P1378 油滴扩展

solution

这是一道很值得反思的题目
首先关于double的基本用法就非常不熟悉

  1. int + 0.0 = double int转化成double的方法
  2. 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;
  
}

posted @ 2020-02-12 22:46  KingBenQi  阅读(87)  评论(0编辑  收藏  举报