Computational Geometry? HDU - 4216(基础dp)

Computational Geometry? HDU - 4216

 Computational geometry is a branch of computer science devoted to the study of algorithms which can be stated in terms of geometry. It often comes up with charming shapes and ideas.
In this problem, our poor princess is trapped in a castle by some bad guys again, yeah, again. So, let's seize the chance to be a hero.
Right now, the beautiful princess is in the original point of a Cartesian coordinate system, for simplification, the castle is treated as a coordinate system, like a common computational geometry problem.
There is a bomb which can be exploded anytime, and it locates at (Xo, Yo) in the castle. To save the princess, we need design a route for her to leave away the bomb as far as possible. But she already has a plan written on her notebook, which contains some vectors, and she insists on escaping in the vectors’ direction one by one, that is, if she is in point(0, 0), and the vector is (X, Y), she will be in point(X, Y) if she escapes in this vector.
You get her notebook now, and find princess's plan is a not a good plan sometimes. Then you decide to help the princess to make some slight modification, you can change the order of those vectors, and/or reverse some vectors, that is, change vector (X, Y) to vector (-X, -Y).
We want to know the maximum distance to the bomb after modification.

Input
The first line contains a single integer T, indicating the number of test cases. Each test case begins with three integers N, Xo, Yo. Then N lines following, each line contains two integers, Xi and Yi, indicating a vector.

Technical Specification
1. 1 <= T <= 100
2. 1 <= N <= 100
3. -100 <= Xi, Yi <= 100
4. -10 000 <= Xo, Yo <= 10 000

Output
For each test case, output the case number first, then the distance rounded to three fractional digits.
Sample Input

3
1 1 1
1 1
2 2 3
-1 2
1 -2
3 3 0
2 3
3 2
1 -1

Sample Output

Case 1: 2.828
Case 2: 7.000
Case 3: 9.849

题意:

给定一个炸弹位置,从人的初始位置是原点,给定几个向量方向,其中可以沿着这个向量方向走,也可以沿着反向走,先走哪个方向顺序随便,问最远能离炸弹坐标多远

分析:

因为坐标范围-10000~10000,为了能让dp数组存下来坐标,我们把坐标都加10000,这样就都成正的了,枚举每个纵坐标,利用dp分别算出每个纵坐标下的最大横坐标x值和最小横坐标x值,因为最大距离肯定在两头的点处取,并且每次dp只和前一次的dp情况有关,所以记录前多少个点的部分我们可以只开2维,利用滚动数组原理
d p [ 2 ] [ 20005 ] [ 2 ] 其中 d p [ i ] [ j ] [ k ] i就是前i个点(只需要用奇偶表示,j是枚举的纵坐标,k是最大值或最小值)

最后遍历一遍纵坐标找出最大距离即可

code:

  #include<cstdio>
  #include<cstring>
  #include<cmath>
  using namespace std;
  #define D 10000
  #define max(a,b) ((a)>(b)?(a):(b))
  #define min(a,b) ((a)<(b)?(a):(b))
  int num[105][2];
  int dp[2][20005][2];
  //dp[i][j][0] 前i个在纵坐标j处横坐标的最小值
  //dp[i][j][1] 前i个在纵坐标j处横坐标的最大值
  int T,n,x,y;
  double dis(int a,int b)
  {
      double c=(double)a,d=(double)b;
      return sqrt((c-x)*(c-x)+(d-y)*(d-y));
  }
  int main()
  {
      scanf("%d",&T);
      for(int cas=1; cas<=T; ++cas)
      {
          scanf("%d%d%d",&n,&x,&y);
          x+=D;
          y+=D;
          for(int i=1; i<=n; ++i)
          {
              scanf("%d%d",&num[i][0],&num[i][1]);
          }
          memset(dp,-1,sizeof(dp));
          //初始化
          dp[0][D][0]=dp[0][D][1]=D;
          for(int i=1; i<=n; ++i)
          {
              for(int j=0; j<=20000; ++j)
                  for(int k=0; k<2; ++k)
                  {
                      if(dp[(i-1)&1][j][k]!=-1)
                      {
                          //更新dp[i][j+num[i][1]][0]最小值
                          if(dp[i&1][j+num[i][1]][0]==-1||dp[i&1][j+num[i][1]][0]>dp[(i-1)&1][j][k]+num[i][0])
                              dp[i&1][j+num[i][1]][0]=dp[(i-1)&1][j][k]+num[i][0];
                          //更新dp[i][j-num[i][1]][0]最小值
                          if(dp[i&1][j-num[i][1]][0]==-1||dp[i&1][j-num[i][1]][0]>dp[(i-1)&1][j][k]-num[i][0])
                              dp[i&1][j-num[i][1]][0]=dp[(i-1)&1][j][k]-num[i][0];
                          //更新dp[i][j+num[i][1]][0]最大值
                          if(dp[i&1][j+num[i][1]][1]==-1||dp[i&1][j+num[i][1]][1]<dp[(i-1)&1][j][k]+num[i][0])
                              dp[i&1][j+num[i][1]][1]=dp[(i-1)&1][j][k]+num[i][0];
                          //更新dp[i][j-num[i][1]][0]最大值
                          if(dp[i&1][j-num[i][1]][1]==-1||dp[i&1][j-num[i][1]][1]<dp[(i-1)&1][j][k]-num[i][0])
                              dp[i&1][j-num[i][1]][1]=dp[(i-1)&1][j][k]-num[i][0];
                      }
                  }
          }
          double dist=0.0;
          //找距离最大值
          for(int i=0; i<=20000; ++i)
              for(int j=0; j<2; ++j)
                  if(dp[n&1][i][j]!=-1)
                      dist=max(dist,dis(dp[n&1][i][j],i));
          printf("Case %d: %.3f\n",cas,dist);
      }
      return 0;
  }

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/81113886
今日推荐