zoukankan      html  css  js  c++  java
  • BZOJ 1193 [HNOI2006]马步距离:大范围贪心 小范围暴搜

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1193

    题意:

      给定起点(px,py)、终点(sx,sy)。(x,y < 10000000)

      每一步只能走“日”字(象棋中的马走日),坐标可以为负。

      问你从起点到终点最少走多少步。

     

    题解:

      简化问题:

        (1)从(px,py)到(sx,sy)等价于:从(abs(px-sx), abs(py-sy))到(0,0)。

        (2)从(x,y)到(0,0)等价于:从(y,x)到(0,0)。

        所以原题简化成:从(abs(px-sx), abs(py-sy))到(0,0),并且可以随时交换x,y以保证x > y。

     

      大范围贪心:

        为了方便起见,始终保证x > y。

        那么对于任意一个数据的最短路径都可以等价为如下形式:

        

        左边部分直走(先右下,再右上),右边部分往右上方走,直到接近终点时停止贪心(x+y <= 50)。

        同时为了保证没有过多的直走(直走会浪费2个距离),设定直走的前提为:

          右边区域的长宽x,y满足:((x-4)/y) > 2

          也就是:x-4 > y*2

        每直走一次,ans+=2。往右上走一次,ans++。

     

      小范围暴搜:

        bfs.

        很好写,不说了。。。

        注意:为了不偏离终点太远,限定可继续搜索的点要满足:abs(nx)<=100 && abs(ny)<=100

     

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <stdlib.h>
      5 #include <queue>
      6 #define MAX_R 105
      7 
      8 using namespace std;
      9 
     10 const int dx[]={1,2,1,2,-1,-2,-1,-2};
     11 const int dy[]={2,1,-2,-1,2,1,-2,-1};
     12 
     13 struct Coor
     14 {
     15     int x;
     16     int y;
     17     Coor(int _x,int _y)
     18     {
     19         x=_x;
     20         y=_y;
     21     }
     22     Coor(){}
     23 };
     24 
     25 int x,y;
     26 int px,py;
     27 int sx,sy;
     28 int ans=0;
     29 int dis[MAX_R][MAX_R];
     30 bool vis[MAX_R][MAX_R];
     31 queue<Coor> q;
     32 
     33 void read()
     34 {
     35     cin>>px>>py>>sx>>sy;
     36     x=abs(px-sx);
     37     y=abs(py-sy);
     38 }
     39 
     40 Coor get_front()
     41 {
     42     Coor now=q.front();
     43     q.pop();
     44     return now;
     45 }
     46 
     47 void insert(Coor now)
     48 {
     49     if(vis[now.x][now.y]) return;
     50     q.push(now);
     51     vis[now.x][now.y]=true;
     52 }
     53 
     54 void bfs()
     55 {
     56     memset(dis,-1,sizeof(dis));
     57     dis[x][y]=0;
     58     insert(Coor(x,y));
     59     while(!q.empty())
     60     {
     61         Coor now=get_front();
     62         int nx=now.x;
     63         int ny=now.y;
     64         if(nx==0 && ny==0) return;
     65         if(abs(nx)>100 || abs(ny)>100) continue;
     66         for(int i=0;i<8;i++)
     67         {
     68             int tx=nx+dx[i];
     69             int ty=ny+dy[i];
     70             if(dis[tx][ty]==-1)
     71             {
     72                 dis[tx][ty]=dis[nx][ny]+1;
     73                 insert(Coor(tx,ty));
     74             }
     75         }
     76     }
     77 }
     78 
     79 void solve()
     80 {
     81     while(x+y>50)
     82     {
     83         if(x<y) swap(x,y);
     84         if(x-4>y*2)
     85         {
     86             x-=4;
     87             ans+=2;
     88         }
     89         else
     90         {
     91             x-=2;
     92             y--;
     93             ans++;
     94         }
     95     }
     96     bfs();
     97     ans+=dis[0][0];
     98 }
     99 
    100 void print()
    101 {
    102     cout<<ans<<endl;
    103 }
    104 
    105 int main()
    106 {
    107     read();
    108     solve();
    109     print();
    110 }
  • 相关阅读:
    linux权限补充:rwt rwT rws rwS 特殊权限
    关于Linux操作系统下文件特殊权限的解释
    Java学习笔记——Java程序运行超时后退出或进行其他操作的实现
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 判断名次
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 日期计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 概率计算
    Java实现 蓝桥杯 算法提高 复数四则运算
  • 原文地址:https://www.cnblogs.com/Leohh/p/7482581.html
Copyright © 2011-2022 走看看