zoukankan      html  css  js  c++  java
  • hdu 5885 XM Reserves (FFT建模)

    Problem Description

    As an eligible Ingress Resistance Agent you should know your power source, the Exotic Matter.
    We call it XM, which is the driving force behind all of our actions in Ingress.
    XM allows us to construct items through hacking portals, to attack enemy portals, make links and create fields.
    We try to collect XM from the ground. XM concentration come from location based services, meaning that areas with a lot of foot traffic have higher amounts versus places that don't.
    You can collect XM by moving through those areas.
    The XM will be automatically harvested by your Scanner when it is within your interaction circle/range.
    Alice decides to select a location such that she can collect XM as much as possible.
    To simplify the problem, we consider the city as a grid map with size `n*m' numbered from (0,0) to (n1,m1).
    The XM concentration inside the block (i,j) is p(i,j).
    The radius of your interaction circle is r.
    We can assume that XM of the block (i,j) are located in the centre of this block.
    The distance between two blocks is the Euclidean distance between their centres.

    Alice stands in the centre of one block and collects the XM.
    For each block with the distance d smaller than r to Alice, and whose XM concertation is p(i,j), Alice's scanner can collects p(i,j)/(1+d) XM from it.
    Help Alice to determine the maximum XM which she can collect once he stands in the centre of one block.
     
    Input
    There are multiple cases.
    For each case, the first line consists two integers n,m (1n,m500) and one float-point number r (0r300).
    Each of the following n line consists m non-negative float-point numbers corresponding to the XM concentrations inside each blocks.
    Output
    For each case, output the maximum XM which Alice can collect in one line.
    Your answers should be rounded to three decimal places.
     
    Sample Input
    3 3 1
    1 3 6
    7 9 4
    2 8 1
    3 3 2
    1 3 6
    7 9 4
    2 8 1
    5 5 1.
    5 4 3 2 9
    1 3 4 3 2
    8 9 4 3 2
    1 2 3 0 1
    2 6 3 4 3 1
     
    Sample Output
    9.000
    24.142
    17.956
     
    题意就是给你一个n*m的格子,每个格点上有一个p[i,j]
    让你选取一个位置,对于所有在以这个点为中心,半径为r的圆内的点的Σp(i,j)/(d+1)最大, d为点到圆心的距离
     
    思路:我们可以对于每个点统计它能对那些格点造成的贡献,然后我们遍历每一个格点就能找到答案了
    我们从坐标变换的角度来思考,假如一个点的坐标为(x,y),圆心跟它的坐标差为(dx,dy)那么圆心的坐标
    就是(x+dx,y+dy),由于格点横纵坐标都是整数,我们可以在整数上离散化dx,dy,实际上-r<=dx,dy<=r
    那么我们对于一个格点,如果它当作圆心(也就是我们选取的位置),剩下能对它产生贡献的点(称为贡献点)都有一个共同的特性
    那就是对于每一个贡献点经过一个(dx,dy)的向量偏移后都会到达圆心,即对于所有贡献点(xi+dx,yi+dy)都相等
    联想到FFT是来求什么的?两个多项式做乘积,能得出结果中每个幂次的系数,我们把每个圆心的坐标看成是多项式乘积结果的每个幂次
    就把这个问题转化成了一个卷积的问题了
    不要忘了坐标是二维的,我们就把坐标转换成一维的, (x,y)→x*M+j (M=max(n+2R,m+2R))
    我们看下叉姐的题解...
    为什么要用M呢?为什么要加个2R呢?   我们注意到dx,dy是有可能是负数,为了避免这种情况我们在定义坐标转换的时候把dx,dy都加上R对应图上B数组
    这样一行原本m个数,最后经过dx,dy平移后就有了m+2*R种位置
    举个例子B[(-2+R)*M+3+R]里面存的其实是向量(2.3),即横坐标-2,纵坐标+3
      1 #include <bits/stdc++.h>
      2 
      3 using namespace std;
      4 const int maxn = 1<<21;
      5 const double pi = acos(-1.0);
      6 #define fft FFT
      7 #define r real
      8 struct Complex
      9 {
     10     double r,i;
     11     Complex(double _r,double _i):r(_r),i(_i){}
     12     Complex(){}
     13     Complex operator +(const Complex &b)
     14     {
     15         return Complex(r+b.r,i+b.i);
     16     }
     17     Complex operator -(const Complex &b)
     18     {
     19         return Complex(r-b.r,i-b.i);
     20     }
     21     Complex operator *(const Complex &b)
     22     {
     23         return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
     24     }
     25 };
     26 void change(Complex y[],int len)
     27 {
     28     int i,j,k;
     29     for(i = 1, j = len/2;i < len-1;i++)
     30     {
     31         if(i < j)swap(y[i],y[j]);
     32         k = len/2;
     33         while( j >= k)
     34         {
     35             j -= k;
     36             k /= 2;
     37         }
     38         if(j < k)j += k;
     39     }
     40 }
     41 void fft(Complex y[],int len,int on)
     42 {
     43     change(y,len);
     44     for(int h = 2;h <= len;h <<= 1)
     45     {
     46         Complex wn(cos(-on*2*pi/h),sin(-on*2*pi/h));
     47         for(int j = 0;j < len;j += h)
     48         {
     49             Complex w(1,0);
     50             for(int k = j;k < j+h/2;k++)
     51             {
     52                 Complex u = y[k];
     53                 Complex t = w*y[k+h/2];
     54                 y[k] = u+t;
     55                 y[k+h/2] = u-t;
     56                 w = w*wn;
     57             }
     58         }
     59     }
     60     if(on == -1)
     61         for(int i = 0;i < len;i++)
     62             y[i].r /= len;
     63 }
     64 Complex a[maxn],b[maxn];
     65 int n,m;
     66 double rr;
     67 int main()
     68 {
     69     //freopen("de.txt","r",stdin);
     70     while (~scanf("%d%d%lf",&n,&m,&rr)){
     71         int R = ceil(rr);
     72         int M = max(n,m)+2*R;
     73         int len = 1;
     74         while (len<=M*M) len<<=1;
     75         for (int i=0;i<len;++i)
     76             a[i]=Complex(0.0,0.0),b[i]=Complex(0.0,0.0);
     77         for (int i=0;i<n;++i){
     78             for(int j=0;j<m;++j){
     79                 double p;
     80                 scanf("%lf",&p);
     81                 a[i*M+j]=Complex(p,0);
     82             }
     83         }
     84         for (int i=-R;i<=R;++i){
     85             for (int j=-R;j<=R;++j){
     86                 if (sqrt(i*i+j*j)<rr)
     87                     b[(i+R)*M+j+R]=Complex(1.0/(sqrt(i*i+j*j)+1),0.0);
     88             }
     89         }
     90         FFT(a,len,1);
     91         FFT(b,len,1);
     92         for (int i=0;i<len;++i)
     93             a[i] = a[i]*b[i];
     94         FFT(a,len,-1);
     95         double ans = 0;
     96         for (int i=0;i<n;++i){
     97             for(int j=0;j<m;++j)
     98                 ans = max(ans,a[(i+R)*M+j+R].r);//答案让求实数的时候后面"+0.5"精度处理就不加了
     99         }
    100         printf("%.3lf
    ",ans);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    java 基础(Collections 工具类的常用方法)
    Java 基础( Map 实现类: Properties)
    Java 基础(Map)
    Java 基础(集合三)
    Java 基础(集合二)
    Java 基础(集合一)
    Java 基础(Annotation)
    CentOS7 系统 springboot应用启动脚本
    GenericObjectPool源码分析
    问题springboot项目启动报错
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7407471.html
Copyright © 2011-2022 走看看