UVA10618 跳舞机 Tango Tango Insurrection
有四个踩踏板,不同的踩踏方式消耗不同的力气
问最小花费的力气
F[ i ] [ a] [b ][ s] , s 是上一次哪只角移动了( 0 ,1,2 )
https://www.luogu.com.cn/problem/UVA10618
#include<iostream> #include <cstring> #include <algorithm> const int N =1003; #define inf 1e9 #define UP 0 #define LEFT 1 #define RIGHT 2 #define DOWN 3 char str[N] ,opt[]=".LR"; int n,f[N][5][5][3], op[N][4][4][3]; int get(int a,int b){ if(a == b) return 3; if(a+b == 3) return 7; return 5; } int energy(int i,int a,int b,int s,int g,int t,int &ta,int &tb){ ta=a,tb=b; if(g == 1) ta=t; else if(g == 2) tb=t; if(ta == tb) return -1; if(ta == RIGHT && tb == LEFT) return -1; if(a == RIGHT && tb != b) return -1; if(b == LEFT && ta != a) return -1; int res; if(g == 0) res=0; else if(g != s) res=1; else{ if(g == 1) res=get(a,ta); else res=get(b,tb); } return res; } void mov(int i,int a,int b,int s,int g,int t){ int ta,tb; int E=energy(i,a,b,s,g,t,ta,tb); if(E < 0) return; int cost=f[i+1][ta][tb][g]+E; int &v=f[i][a][b][s]; if(cost < v){ v=cost; op[i][a][b][s]=g*4+t; } } void sov(){ int i ,a,b; for(i=n-1;i>=0;i--) for(a=0;a<4;a++) for(b=0;b<4;b++) if(a!=b) { for(int s=0;s<3;s++){ f[i][a][b][s] = inf ; if(str[i]=='.'){ mov(i,a,b,s,0,0) ; for(int t=0;t<4;t++){ mov(i,a,b,s,1,t); mov(i,a,b,s,2,t); } } else{ if(str[i]=='U'){ mov(i,a,b,s,1,0); mov(i,a,b,s,2,0); } else if(str[i]=='L'){ mov(i,a,b,s,1,1) ; mov(i,a,b,s,2,1); } else if(str[i]=='R'){ mov(i,a,b,s,1,2); mov(i,a,b,s,2,2); } else{ mov(i,a,b,s,1,3) ; mov(i,a,b,s,2,3) ; } } } } } signed main () { while(std::cin>>str){ if(str[0] == '#') break; n=strlen(str); memset(f,0,sizeof f); sov(); int a=LEFT,b=RIGHT,s=0; for(int i=0;i<n;++i){ int g=op[i][a][b][s]/4; int t=op[i][a][b][s]%4; printf("%c",opt[g]); s=g; if(g == 1) a=t; else if(g == 2) b=t; } puts(""); } }