题目描述
为了将这些生产的玩具销往海外,晚上江北的玩具公司灯火通明。安安是公司的保安,当所有工作人员离开公司后,他要把公司里所有的门都关闭。房间的门有些是关闭的,有些是打开的。为了察看该公司里所有房间的门是否关闭,该公司安装了物联网智能门禁检测器,在保安配备的设备中会显示哪些房间的门已经关闭,哪些房间的门还是打开的。
该公司共有 x 层,每层楼各有 y 个房间,每层楼的最左边和最右边各有一个楼梯。也就是说,这家公司可以表示为 x 行和 y+2 列的矩形,其中第一列和最后一列表示楼梯,中间 y列表示房间。(注意:最左边的是第一列楼梯)保安安安目前站在一楼的第一列的楼梯处。他必须一个房间一个房间去关门(注:关门在瞬间完成,所以关门时间可忽略不计),但安安只可以可用 1 单位时间完成以下内容之一:爬楼梯到达上一层楼,从房间到达相邻的房间或楼梯,从楼梯到达相邻的房间(也就是说向上、向左、向右“走一格”各需要 1 单位时间)。请你帮助安安计算关闭所有门的最短的单位时间。
特别提醒:安安是从最下面一层的第一列的楼梯处出发,他不必回到起始位置,并且他不用访问已经关门的房间。当所有房门都提示关闭时,他的任务就完成了。
输入
第一行输入两个整数 x 和 y,分别表示总共的楼层数和每层的房间数。
下面的 x 行,每行输入 y + 2 个二进制的字符串,依次表示某个楼层的左楼梯,y 个房间,右楼梯,其中 0 表示门是关闭的,1 表示门是打开的。楼层是从下往上递增的,因此最后一行代表底层(就是第一层)。
每行字符串的第一个和最后一个字符分别表示左侧楼梯和右侧楼梯,所以它们始终为 0。
输出
输出一个整数,表示将所有门都关闭的最短时间。
样例输入 Copy
【样例1】 2 2 0010 0100 【样例2】 3 4 001000 000010 000010 【样例3】 4 3 01110 01110 01110 01110
样例输出 Copy
【样例1】 5 【样例2】 12 【样例3】 18
提示
样例一:安安先到达第一层楼的第一个房间,然后他可以使用左右两侧的楼梯到达第二层楼的第二个房间,看看使用哪个楼梯到达的时间最短,此样例使用左右两侧的楼梯的时间都相同。
样例二:安安先到达第一层楼的第四个房间,使用右侧楼梯到达第二层楼的第四个房间,再使用右侧楼梯,最后到达第三层楼的第二个房间。
样例三:他将走过所有的房间,在每层楼的左右楼梯之间交替。
1<=x<=15 且 1<=y<=100
笑着活下去 :)
这个题和第六场的打怪兽题都需要用到“动态规划”..最好是去百度一下,或者..
(3条消息) 【算法】详解动态规划_如风逝去-CSDN博客_动态规划
用上面这两个链接简单了解一下~我就是通过上面两位大佬的讲解初步掌握了一点点.; )
关于这个题,学长也出了博客~:
关灯 - Wraith_Fiee的博客 (myqcloud.com)
了解完之后大家应该就都有能力解决这道题了~
不过 还是献丑分享一下我的代码(抄得学长的答案):
#include <algorithm>
#include <cstdio>
using namespace std;
int main(){
int x,y,i,j,l[20],r[20]={0};
scanf("%d %d",&x,&y);
int a[20][110];
for(i=x;i>=1;i--){
for(j=0;j<=y+1;j++)
scanf("%1d",&a[i][j]);
}
fill(l,l+20,y+1);
//r[i]数组表示第i层最靠右的开门房间的位置 l[i]数组表示第i层最靠左的开门房间的位置
int dp[20][2]={0};
//dp[i][0]表示把从1~i层所有的门关上,然后回到i层左楼梯所需要的时间。
//dp[i][1]表示把从1~i层所有的门关上,然后回到i层右楼梯所需要的时间。
for(i=x;i>=1;i--){
for(j=0;j<=y+1;j++)
if(a[i][j]==1){
l[i]=min(l[i],j);
r[i]=max(r[i],j);
}
}
dp[1][1]=y+1;
if(r[1]!=0){
dp[1][0]=2*r[1];
}
int ans =r[1]; //ans=r[1]是为了解决输入中有x为1的特殊情况。
for(i=2;i<=x;i++){
if(r[i]!=0){
//如果该层有开着的门。
ans=min(dp[i-1][0]+1+r[i],dp[i-1][1]+(y+1-l[i])+1);
//ans表示从1~i层,把所有的门关掉所需的时间。
dp[i][0]=min(dp[i-1][0]+1+2*r[i],dp[i-1][1]+y+1+1);
dp[i][1]=min(dp[i-1][0]+(y+1)+1,dp[i-1][1]+1+(y+1-l[i])*2);
}
else{
//如果该层没有开着的门,就直接上楼~
dp[i][0]=dp[i-1][0]+1;
dp[i][1]=dp[i-1][1]+1;
}
}
printf("%d",ans);
}
如有纰漏,请多多指正!!!
PS:如果回去继续看那道题应该会看到红色加粗的三个字 “只可以”。
我自己不认真仔细,没读懂题意,还去跟棒棒糖说这题有错,老师就加粗了这三个字回复我。好羞愧,真想穿越回去扇自己一巴掌: (