作比赛的时候想到了dp,dp大致思路是对的,但是没有考虑到特殊情况,而且代码一堆bug,因此wa;
最开始想用dfs,但用pow算次方算错了就没用,注意pow是浮点数类型,用其他变量表示可能会错;
dfs写法:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m,l[20],r[20],a[20],b[20],ans;
char mp[20][110];
void dfs(int step,int cnt,int x){
if(cnt==-1||b[cnt]==0){ //判断是否到头,如果到了走完了所有层,或者剩余层都没有1,则dfs结束。
ans=min(ans,step);
return ;
}
int step_l=step+x+1+r[cnt];
int step_r=step+(m+1-x)+1+(m+1-l[cnt]);
if(a[cnt]==0) dfs(step+1,cnt-1,x);//如果这一层没有1,则直接走向下一层
//这里if里面dfs后面可以加个return ,因为没有1可以不用走下面的两个dfs
dfs(step_l,cnt-1,r[cnt]);
if(step_l!=step_r) dfs(step_r,cnt-1,l[cnt]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
//l[i]=0,r[i]=0;
l[i]=0,r[i]=0;
}
for(int i=0;i<n;i++){
for(int j=0;j<=m+1;j++){
cin>>mp[i][j];
if(l[i]==0&&mp[i][j]=='1') l[i]=j;
if(mp[i][j]=='1') r[i]=j;
}
if(l[i]==0) a[i]=0;
else a[i]=1;
}
b[0]=a[0];
for(int i=1;i<n;i++){
b[i]=a[i]+b[i-1];
}
ans=2000;
dfs(r[n-1],n-2,r[n-1]);
printf("%d\n",ans);
return 0;
}
dp:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m,l[20],r[20],ans;
char mp[20][110];
int dp_r[20],dp_l[20],a[20],b[20];
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
//l[i]=0,r[i]=0;
l[i]=0,r[i]=0;
}
for(int i=0;i<n;i++){
for(int j=0;j<=m+1;j++){
cin>>mp[i][j];
if(l[i]==0&&mp[i][j]=='1') l[i]=j;
if(mp[i][j]=='1') r[i]=j;
}
if(l[i]==0) a[i]=0;
else a[i]=1;
}
b[0]=a[0];
for(int i=1;i<n;i++){
b[i]=a[i]+b[i-1];//记录刚到达i层时,还有b[i]层要关
}
ans=r[n-1];
l[n-1]=r[n-1];//因为第一层肯定是从左边上去,所以必定以r为进入下一层的起点才是最优的,
//-因为如果从l为起点,那么要到r然后又返回l再上去,这和r为起点是等效的,但是刚开始的时候我忘了
//-更新l[n-1]为r[n-1]导致wa
dp_l[n-1]=r[n-1],dp_r[n-1]=r[n-1];
int t=n-1;//表示上一个必须要走的层
for(int i=n-2;i>=0;i--){
if(b[i]==0){ //如果为零,那么不用继续走了
ans=min(dp_l[i+1],dp_r[i+1]);
break;
}
if(l[i]==0){//到这来说明还有要走的,如果这一层不用走,那么上到上一层去
dp_l[i]=dp_l[i+1]+1;
dp_r[i]=dp_r[i+1]+1;
ans=min(dp_l[i],dp_r[i]);
continue;
}
dp_l[i]=min(dp_l[i+1]+2*m+3-l[i]-l[t],dp_r[i+1]+2*m+3-l[i]-r[t]);//dp_l[i+1]用i+1做下标是因为这样方便表示dp
//-用t表示l,r下标防止算到空层
dp_r[i]=min(dp_l[i+1]+l[t]+r[i]+1,dp_r[i+1]+r[t]+r[i]+1);
if(l[i]==r[i]){
dp_l[i]=min(dp_l[i],dp_r[i]);
dp_r[i]=dp_l[i];
}
ans=min(dp_l[i],dp_r[i]);
t=i;//开始写成了t--;导致一直wa,可以说这也是个常见的错误,更换状态时,更换方式不正确,应该是跳跃的更换,因为
//-有空格情况下,这一层用完上一次的l,r,应该是更新到当前,而不是减一,不然t就变成了空格层。
//-往上一不等于跳跃变更。
}
printf("%d\n",ans);
return 0;
}
注意:特判一些特殊情况;
时常注意一些变量的转化是否正确合理。