今天写了好久都没写出来,后来看别人代码才过了。
刚开始写的时候,觉得决策十分复杂,一直在讨论,写了很长。后来打印决策的时候遇到了更大的麻烦,只好用dfs递归去打印。代码长到爆炸,而且还WA了。
后来看别人代码,学到几个技巧。
在dp时直接暴力枚举所有决策,然后写一个函数判断是否合法即可。
能量消耗也不需要在dp时判断,直接交给函数处理就好了。
最开始之所以WA是因为路径保存错了。我只保存了一维的路径,其实要保存四维的路径,这样才能保证记录了所有状态的下一个状态,下一个状态用结构体表示。
代码
#include<bits/stdc++.h>
#define INF 0X3F3F3F3F
using namespace std;
struct Node
{
int l,r,s;
}path[80][5][5][5];
char str[80];
int dp[80][5][5][5];
int len;
int ok(int l,int r,int nl,int nr)
{
if(l==nl&&r==nr) return 1;
else if(l==nl) return (nr!=l&&l!=2);
else if(r==nr) return (nl!=r&&r!=4);
else return 0;
}
int cost(int f,int t,int last,int now)
{
if(last!=now) return 1;
else if(f==t) return 3;
else if((f+t)%2) return 5;
else return 7;
}
int dfs(int i,int a,int b,int s)
{
if(i==len) return 0;
int& ans=dp[i][a][b][s];
Node& p=path[i][a][b][s];
if(ans>=0) return ans;
ans=INF;
if(str[i]=='.')
{
ans=min(ans,dfs(i+1,a,b,0));
p.l=a,p.r=b,p.s=0;
for(int j=1;j<=4;j++)
{
if(ok(a,b,j,b))
{
int temp=dfs(i+1,j,b,1)+cost(a,j,s,1);
if(temp<ans)
{
ans=temp;
p.l=j,p.r=b,p.s=1;
}
}
if(ok(a,b,a,j))
{
int temp=dfs(i+1,a,j,2)+cost(b,j,s,2);
if(temp<ans)
{
ans=temp;
p.l=a,p.r=j,p.s=2;
}
}
}
}
else
{
int pos;
switch (str[i])
{
case 'U':pos=1;break;
case 'D':pos=3;break;
case 'L':pos=4;break;
case 'R':pos=2;break;
}
if(ok(a,b,pos,b))
{
int temp=dfs(i+1,pos,b,1)+cost(a,pos,s,1);
if(temp<ans)
{
ans=temp;
p.l=pos,p.r=b,p.s=1;
}
}
if(ok(a,b,a,pos))
{
int temp=dfs(i+1,a,pos,2)+cost(b,pos,s,2);
if(temp<ans)
{
ans=temp;
p.l=a,p.r=pos,p.s=2;
}
}
}
return ans;
}
void print()
{
int la=4,lb=2,ls=0;
int a=path[0][la][lb][ls].l;
int b=path[0][la][lb][ls].r;
int s=path[0][la][lb][ls].s;
for(int j=1;j<=len;j++)
{
if(s==0) printf(".");
else if(s==1) printf("L");
else printf("R");
la=a;
lb=b;
ls=s;
a=path[j][la][lb][ls].l;
b=path[j][la][lb][ls].r;
s=path[j][la][lb][ls].s;
}
puts("");
}
int main()
{
while(1)
{
scanf("%s",str);
if(str[0]=='#') break;
len=strlen(str);
memset(dp,-1,sizeof(dp));
dfs(0,4,2,0);
print();
}
return 0;
}