【递推】【HDU 2073】无限的路 (找规律)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2073

意外之喜  还挺不错的一道题目

 仔细观察不难发现   其实整个路线只有这两种线(绿色跟红色)

并且在移动过程中[x,y]的改变(红线部分)总是遵循这两种规律[x+1,y-1]或者[x-1,y+1],设x+y=z

在同一条红线中z的值是不变的

既然如此 我们不如直接用x+y来计算红线部分的总值,忽略x与y的具体数值

我们定义一个数组p1[z]来保存红线的前缀和

计算公式也很容易看出来p1[0] = 0;  p[i] = p[i-1]+i*g;     // double g = sqrt(2);   很容易看出来 第i条红线恰好有条长度为sqrt(2)的线段

那么现在红线部分就搞定了  

接下来定义一个数组p2[z]来保存绿线的前缀和

同样用开平方根的方式计算第x跟绿线的长度   第x根绿线的长度为sqrt(x^2+(x+1)^2);

p2[0] = 0;  p2[i] = p[i-1]+sqrt(i^2+(i-1)^2);

此时我们只需要判断出给出的坐标点位于哪条红线上,将这条红线之前的前缀和加到sum上

再根据x的值判断这之前有多少条绿线 再将这些绿线的前缀和加到sum上

现在就只剩下最后一个问题了  即加上最后一段的距离


比如计算[3,1](距离[0,0])的长度

加上前(3+1)-1条红线 再加上前(3+1)条绿线 再加上最后一段的距离

对于[3,1],最后一段的距离是[0,4]->[1,3]->[2,2]->[3,1];(发现恰好为三个g的距离)

再尝试观察几个其他的点  发现最后一段距离恰好为x个g的距离

那么公式就出来了  sum[x,y]=p1[x+y-1]+p2[x+y]+x*g;

那么我们只需要计算一次[x1,y1]的sum,再计算一次[x2,y2]的sum进行相减取绝对值

最后的结果便出来了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 double p1[210],p2[210];
 4 double g = sqrt(2);
 5 int main()
 6 {
 7     int i,j,x1,y1,x2,y2;
 8     double num1,num2;
 9     p1[0] = 0.0;
10     for(int i = 1;i <= 205;i++)
11         p1[i] = p1[i-1]+(i)*g;
12     p2[0] = 0;
13     for(int i = 1;i <= 205;i++)
14         p2[i] = sqrt(i*i+(i-1)*(i-1))+p2[i-1];
15     int n;
16     cin >> n;
17     while(n--)
18     {
19         scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
20         num1 = p1[x1+y1-1]+x1*g+p2[x1+y1];
21         num2 = p1[x2+y2-1]+x2*g+p2[x2+y2];
22         printf("%.3lf\n",fabs(num1-num2));
23     }
24     return 0;
25 }

猜你喜欢

转载自www.cnblogs.com/duny31030/p/8974216.html