0w1

POI 2 Stage 2 The Right-Turn Drivers' Club ( DP, BFS )

http://main.edu.pl/en/archive/oi/2/kpk

題意:
給一張圖,有若干障礙物,給始點和終點,問是否可以不左轉不倒回從始點走到終點,可以的話輸出最短路徑的方案。

資料規模:
In the first line of the standard input there are two integers separated by a single space: the number of rows and the number of columns . In each of the following lines of the file there is a description of the corresponding row of the map. Such a description has a form of one word of length consisting of digits and . The digit means that the corresponding square is free, and the digit that it is blocked.
Next, in one line, there are two coordinates of the square , separated by a single space: the row number not greater than and the column number not greater than . In the following line there are two coordinates of the square , written the same way.

解法:
一個頗裸的 DP 和 BFS,DP 記錄方向狀態就能避免左轉或倒走。

時間 / 空間複雜度:
O( N * M )

#include <bits/stdc++.h>
using namespace std;

template< class T1, class T2 >
int upmin( T1 &x, T2 v ){
  if( x <= v ) return 0;
  x = v; return 1;
}

const int MAXN = 100;
const int MAXM = 100;
const int dx[] = { 0, 1, 0, -1 };
const int dy[] = { 1, 0, -1, 0 };

int N, M;
string G[ MAXN ];
int sx, sy, gx, gy;

struct qqq{
  int a, b, c;
  qqq(){}
  qqq( int x, int y, int z ){
    a = x, b = y, c = z;
  }
};

int dp[ MAXN ][ MAXM ][ 4 ];
qqq pre[ MAXN ][ MAXM ][ 4 ];

signed main(){
  ios::sync_with_stdio( 0 );
  cin >> N >> M;
  for( int i = 0; i < N; ++i ){
    cin >> G[ i ];
  }
  cin >> sx >> sy >> gx >> gy;
  --sx, --sy, --gx, --gy;
  {
    memset( dp, 0x3f3f3f3f, sizeof( dp ) );
    queue< qqq > que;
    for( int di = 0; di < 4; ++di ){
      dp[ sx ][ sy ][ di ] = 0;
      que.push( qqq( sx, sy, di ) );
    }
    while( not que.empty() ){
      int x, y, dir; x = que.front().a, y = que.front().b, dir = que.front().c; que.pop();
      if( x == gx and y == gy ) break;
      for( int di = 0; di < 4; ++di ){
        if( ( di + 1 ) % 4 == dir ) continue;
        if( ( di + 2 ) % 4 == dir ) continue;
        int nx = x + dx[ di ];
        int ny = y + dy[ di ];
        if( not ( 0 <= nx and nx < N and 0 <= ny and ny < M ) ) continue;
        if( G[ nx ][ ny ] == '1' ) continue;
        if( upmin( dp[ nx ][ ny ][ di ], dp[ x ][ y ][ dir ] + 1 ) ){
          pre[ nx ][ ny ][ di ] = qqq( x, y, dir );
          que.push( qqq( nx, ny, di ) );
        }
      }
    }
  }
  int ans = 0x3f3f3f3f, best;
  for( int di = 0; di < 4; ++di ){
    if( upmin( ans, dp[ gx ][ gy ][ di ] ) ){
      best = di;
    }
  }
  if( ans == 0x3f3f3f3f ){
    cout << "NIE\n";
  } else{
    cout << ans + 1 << "\n";
    vector< pair< int, int > > dc;
    for( int x = gx, y = gy, d = best; not ( x == sx and y == sy ); ){
      int px = pre[ x ][ y ][ d ].a, py = pre[ x ][ y ][ d ].b, pd = pre[ x ][ y ][ d ].c;
      dc.push_back( make_pair( px, py ) );
      x = px, y = py, d = pd;
    }
    for( int i = dc.size() - 1; i >= 0; --i ){
      cout << dc[ i ].first + 1 << " " << dc[ i ].second + 1 << "\n";
    }
    cout << gx + 1 << " " << gy + 1 << "\n";
  }
  return 0;
}