大概思路是用
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示当前执行到第
i
i
i个操作,改变了
j
j
j次时回到原点的最大次数,并且此时刚好在原点(这是为了方便转移)。然后每次只需要枚举一个
k
k
k,计算出执行完
(
i
,
k
]
(i,k]
(i,k]这一段操作后再回到原点需要修改几个,就可以进行转移。
少写了一句判断状态是否可行害得我懵逼了好久(感谢xLLLx帮我Debug)
#include <bits/stdc++.h>
using namespace std;
const int N=301;
int n,f[N][N],mx,u[N],r[N];
class FriendlyRobot {
public:
int findMaximumReturns( string s, int m );
};
int d(int k,int i){ //执行k个与i个操作之后都在(0,0),中间需要改多少个,利用了类似前缀和的思想
int x=abs(u[i]-u[k]),y=abs(r[i]-r[k]);
return (x+y)/2;
}
int FriendlyRobot::findMaximumReturns(string s, int m) {
n=s.size();
for(int i=0;i<n;i++)
if (s[i]=='U'||s[i]=='D'){
if (s[i]=='U') u[i+1]=u[i]+1;
else u[i+1]=u[i]-1;
r[i+1]=r[i];
} else{
if (s[i]=='R') r[i+1]=r[i]+1;
else r[i+1]=r[i]-1;
u[i+1]=u[i];
}
memset(f,-1,sizeof f);
for(int i=0;i<=n;i+=2) if (!u[i]&&!r[i]) f[i][0]=0; //这句应该没用
mx=0;
for(int i=0;i<=n;i+=2)
for(int j=0;j<=i/2&&j<=m;j++){
if (f[i][j]==-1) continue; //必须要判断当前状态是否可行(否则会WA得很惨
mx=max(mx,f[i][j]);
for(int k=i+2;k<=n;k+=2){
int w=d(i,k);
if (j+w<=m) f[k][j+w]=max(f[k][j+w],f[i][j]+1);
}
//printf("f[%d][%d]=%d\n",i,j,f[i][j]);
}
return mx;
}