给一个地图,机器人要从左上角走到右下角,机器人重复一定的指令序列,指令只包含向下走和向右走两种,问指令序列的最短长度。
枚举指令序列中向下和向右的个数,然后地图重叠过去。判断能否走到最后的终点,再由终点走到右下角。
感觉上复杂度是n^4的,并且直接判断TLE了...改成按照顺序枚举,先尝试指令序列短的,找到一个可行解就直接输出答案,然后300ms过了..
暂时没想到更好的解法...
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,ans;
char c[210][210];
bool a[210][210];
bool b[211][211];
void add(int x,int y,int nn,int mm) {
for (int i=0;i<=nn;i++) {
for (int j=0;j<=mm;j++) {
if (c[i+x][j+y]=='X') a[i][j]=false;
}
}
}
void calans(int nn,int mm) {
int i,j,tn=n-1,tm=m-1;
for (i=0;i<=nn;i++)
for (j=0;j<=mm;j++) {
a[i][j]=true;
b[i][j]=false;
}
while (tn>nn||tm>mm) tn-=nn,tm-=mm;
if (tn<0||tm<0) return;
for (i=0,j=0;i<n&&j<m;i+=nn,j+=mm)
add(i,j,nn,mm);
b[0][0]=true;
for (i=0;i<=tn;i++)
for (j=0;j<=tm;j++)
if (b[i][j]) {
if (a[i+1][j]) b[i+1][j]=true;
if (a[i][j+1]) b[i][j+1]=true;
}
for (i=tn;i<n;i++)
for (j=tm;j<=m;j++)
if (b[i][j]) {
if (a[i+1][j]) b[i+1][j]=true;
if (a[i][j+1]) b[i][j+1]=true;
}
if (b[nn][mm]&&b[tn][tm])
if (ans==-1) ans=nn+mm;
else ans=min(ans,nn+mm);
}
int updivide(int x,int y) {
return x/y+(x%y!=0);
}
int main() {
int i,j,l;
while (scanf("%d%d",&m,&n)!=EOF) {
memset(c,0,sizeof(c));
for (i=0;i<n;i++)
for (j=0;j<m;j++)
scanf(" %c",&c[i][j]);
ans=-1;
for (l=2;l<n+m-1&&ans==-1;l++) {
for (i=1;l-i>0&&ans==-1;i++)
calans(i,l-i);
}
printf("%d\n",ans);
}
return 0;
}