zoukankan      html  css  js  c++  java
  • 1378 油滴扩展

    难度:普及+/提高

    题目类型:搜索

    提交次数:2

    涉及知识:深搜

    题目描述

    在一个长方形框子里,最多有N(0≤N≤6)个相异的点,在其中任何一个点上放一个很小的油滴,那么这个油滴会一直扩展,直到接触到其他油滴或者框子的边界。必须等一个油滴扩展完毕才能放置下一个油滴。那么应该按照怎样的顺序在这N个点上放置油滴,才能使放置完毕后所有油滴占据的总体积最大呢?(不同的油滴不会相互融合)

    注:圆的面积公式V=pi*r*r,其中r为圆的半径。

    输入输出格式

    输入格式:

    第1行一个整数N。

    第2行为长方形边框一个顶点及其对角顶点的坐标,x,y,x’,y’。

    接下去N行,每行两个整数xi,yi,表示盒子的N个点的坐标。

    以上所有的数据都在[-1000,1000]内。

    输出格式:

    一行,一个整数,长方形盒子剩余的最小空间(结果四舍五入输出)

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const double pi = 3.1415926535;
     7 const double maxx = 1<<20;
     8 int N;//N个点 
     9 double x1, y11,x2, y2;//对角线坐标 
    10 double ans, sum;
    11 struct point{
    12     int x, y;
    13 }p[10];
    14 bool visited[10];
    15 int order[10]; //需要一个存顺序的数组 
    16 double r[10]; //半径 
    17 
    18 double dis(point a, point b){
    19     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    20 }
    21 double calculate(int i){
    22     double ans = maxx;
    23     double a1 = min(abs(p[i].x-x1), abs(p[i].x-x2));
    24     double a2 = min(abs(p[i].y-y11), abs(p[i].y-y2));//算距离边缘的距离
    25     double a = min(a1, a2);//距离边缘的最小距离 
    26     double b = maxx;//根据其他点算出的最小半径 
    27     int flag = 0;
    28     while(1){
    29         if(order[flag]==i) break;
    30         double d = dis(p[order[flag]], p[i]);
    31         b = min(d-r[order[flag]], b);
    32         flag = order[flag]; 
    33     } 
    34     ans = min(a, b); 
    35     if(ans<0) ans = 0;
    36     return ans;
    37 } 
    38 void dfs(int m, int step){//放m号油滴 
    39     if(step == N+1){
    40         ans = max(sum, ans);
    41         return;
    42     }
    43     else{
    44         for(int i = 1; i <= N; i++){
    45             if(!visited[i]){
    46                 visited[i] = true;
    47                 order[m] = i; //链表,m的下一个存i 
    48                 r[i] = calculate(i); //计算i能达到的半径 
    49                 sum += pi*r[i]*r[i];
    50                 dfs(i, step+1);
    51                 visited[i] = false;
    52                 sum -= pi*r[i]*r[i];
    53                 r[i] = 0;
    54             }
    55         }
    56     }
    57 }
    58 int main(){
    59     cin>>N;
    60     cin>>x1>>y11>>x2>>y2;
    61     int i, j;
    62     for(i = 1; i <= N; i++)
    63         cin>>p[i].x>>p[i].y;
    64     double length = abs(x1-x2);
    65     double width = abs(y11-y2);
    66     dfs(0, 1);
    67     cout<<(int)(length*width-ans+0.5);
    68     return 0;
    69 }

    备注:

    欢呼~!!!!

    历时一个小时,基本上是按照自己的构思独立写完的,第一次提交心里特没底,心想别爆0就好,结果得了70分!于是松了口气,因为知道那30分丢在哪(当r<0即一点被包含时,令r=0,标黄那行)。。然后回去一改,就过了!哈哈哈

    写这道题就是为了强化一下自己的搜索。被逼无奈的时候怎么着也能写个暴力骗点分。这道题就是一个赤裸裸的搜索。中间也参考了一下别人的思路,比如那个链表。。当时没有想出来怎么存已放好油滴的顺序(现在想想直接用step做下标就好,不过step是我后加的),最开始dfs的参数就是一个m。不过现在看来m这个参数似乎没啥必要诶。。一个step就够了。

    思路就是爆搜,对于每一个点和它放的顺序算出最小半径。(calculate函数要干的事)

    要注意的细节还是挺多的。没忘了变量都得用double,表扬自己一下。要先把程序结构想清楚。这次我写代码的顺序是:主函数,dfs,calculate,这样比较有逻辑。

    我觉得链表那块我处理的好巧妙啊哈哈哈。

    开始的时候把r[i]=0放到sum-=xxx前面了,还奇怪为啥sum不减少orz。

    y1这个变量真谜,好像跟什么重名了。。怪不得看到的某题解变量设了个y250……

    四舍五入的技巧:(int)(xxx+0.5),好神奇。

    总之,做完这道题还是很有成就感很开心的!

  • 相关阅读:
    socket是什么
    0,1,2 代表标准输入、标准输出、标准错误
    认识程序的执行:从高级语言到二进制,以java为例
    97 条 Linux 运维工程师常用命令总结[转]
    rsync 参数配置说明[转]
    shell 脚本学习之内部变量
    ansible 入门学习(一)
    python 管理多版本之pyenv
    CentOS6 克 隆
    yum 本地仓库搭建
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/6017081.html
Copyright © 2011-2022 走看看