[APIO2013]机器人(DP+SPFA最短路)
生活随笔
收集整理的這篇文章主要介紹了
[APIO2013]机器人(DP+SPFA最短路)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[APIO2013]機器人
description
solution
dpl,r,i,j:dp_{l,r,i,j}:dpl,r,i,j?: 在(i,j)(i,j)(i,j)位置合并編號為[l,r][l,r][l,r]區間內的所有機器人的最小花費
toi,j,k:to_{i,j,k}:toi,j,k?: 從(i,j)(i,j)(i,j)以kkk方向推機器人最終停止的位置,用dfs記憶化搜索模擬即可
dpl,r,i,j=min?{dpl,k,i,j+dpk+1,r,i,j∣l≤i<r}dp_{l,r,i,j}=\min\{dp_{l,k,i,j}+dp_{k+1,r,i,j}\big| l\le i<r\}dpl,r,i,j?=min{dpl,k,i,j?+dpk+1,r,i,j?∣∣?l≤i<r}
dpl,r,i,j+1→toi,j,kdp_{l,r,i,j}+1\rightarrow to_{i,j,k}dpl,r,i,j?+1→toi,j,k? 該轉移就是一層在(i,j)(i,j)(i,j)位置上的最短路,用類bfs的spfa跑即可
code
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define inf 0x3f3f3f3f #define LEN 500000 struct node {int x, y;node(){}node( int X, int Y ) {x = X, y = Y;} }robot[10], to[505][505][4], s[500005], t[500005]; int n, col, row, cnt, top; char room[505][505]; int dx[4] = { 1, 0, -1, 0 }, dy[4] = { 0, -1, 0, 1 }; int f[10][10][505][505]; int id[505][505][4]; bool vis[505][505]; int w[1000005], sum[1000005];node dfs( int x, int y, int k ) {if( id[x][y][k] == cnt ) return node( 0, -1 );id[x][y][k] = cnt;if( to[x][y][k].y ) return to[x][y][k];int dir = k;if( room[x][y] == 'C' ) dir = ( dir + 1 ) % 4;if( room[x][y] == 'A' ) dir = ( dir + 3 ) % 4;int tx = x + dx[dir], ty = y + dy[dir];if( tx < 1 || tx > row || ty < 1 || ty > col || room[tx][ty] == 'x' )return to[x][y][k] = node( x, y );elsereturn to[x][y][k] = dfs( tx, ty, dir ); }void spfa( int l, int r ) {memset( sum, 0, sizeof( sum ) );memset( vis, 0, sizeof( vis ) );int minn = inf, maxx = -inf;for( int i = 1;i <= top;i ++ ) {sum[w[i]] ++;minn = min( minn, w[i] );maxx = max( maxx, w[i] );vis[s[i].x][s[i].y] = 1;}//類后綴數組方法對隊列中當前層位置進行手動排序編號 for( int i = minn + 1;i <= maxx;i ++ ) sum[i] += sum[i - 1];for( int i = top;i;i -- )t[sum[w[i]] --] = s[i];for( int i = 1;i <= top;i ++ )s[i] = t[top - i + 1];int head = 0, tail = 0, now; node u, v;//%LEN:手動進行空間回收利用 while( top || head != tail ) {now = head % LEN + 1;if( head == tail || ( top && f[l][r][s[top].x][s[top].y] < f[l][r][t[now].x][t[now].y] ) )u = s[top], top --;elsehead = now, u = t[head];vis[u.x][u.y] = 0;for( int i = 0;i < 4;i ++ ) {v = to[u.x][u.y][i]; if( v.x && f[l][r][v.x][v.y] > f[l][r][u.x][u.y] + 1 ) {f[l][r][v.x][v.y] = f[l][r][u.x][u.y] + 1;if( ! vis[v.x][v.y] ) {vis[v.x][v.y] = 1;tail = tail % LEN + 1;t[tail] = v;}}}} }int main() {memset( f, 0x3f, sizeof( f ) );scanf( "%d %d %d", &n, &col, &row );for( int i = 1;i <= row;i ++ ) {scanf( "%s", room[i] + 1 );for( int j = 1;j <= col;j ++ )if( room[i][j] < '0' || room[i][j] > '9' )continue;else {int k = room[i][j] - '0';robot[k] = node( i, j );f[k][k][i][j] = 0;}}//to(i,j,k):(i,j)位置按k方向推機器人最終停止的位置 for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )if( room[i][j] == 'x' )continue;elsefor( int k = 0;k < 4;k ++ )cnt ++, to[i][j][k] = dfs( i, j, k );for( int i = 1;i <= n;i ++ )s[top = 1] = robot[i], w[1] = 0, spfa( i, i );//f(l,r,i,j,):在(i,j)位置上合并[l,r]編號內的機器人的最小花費 for( int len = 1;len <= n;len ++ )//區間DP 由小到大 for( int l = 1;l <= n;l ++ ) {int r = l + len;if( r > n ) break;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )for( int k = l;k < r;k ++ )f[l][r][i][j] = min( f[l][r][i][j], f[l][k][i][j] + f[k + 1][r][i][j] );top = 0;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )if( f[l][r][i][j] < inf ) //狀態本身要存在才能進行下一層轉移 s[++ top] = node( i, j ), w[top] = f[l][r][i][j];spfa( l, r );}int ans = inf;for( int i = 1;i <= row;i ++ )for( int j = 1;j <= col;j ++ )ans = min( ans, f[1][n][i][j] );printf( "%d\n", ans < inf ? ans : -1 );return 0; }總結
以上是生活随笔為你收集整理的[APIO2013]机器人(DP+SPFA最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 「JOISC 2020 Day4」治疗计
- 下一篇: [HDU 6157]The Kartin