codeforces 812B. Sagheer, the Hausmeister

题目链接:http://codeforces.com/contest/812/problem/B

题意:n层楼,每层有m个房间,左右两边是楼梯,输入一个n*(m+2)的字符串,字符1代表这个房间灯亮。要想关闭上层的等,低层的灯必须全部关闭。现在问你关闭所有的灯最少移动多少次。

分析:动态规划或者dfs都可以。dp[i][0]代表到达第i层的左边楼梯最短移动,dp[i][1]代表到达第i层的右边楼梯的最短移动。初始化dp[1][0]=0,dp[1][1]=m+1;

    dp[i][0]=min(dp[i-1][0]+r[i-1]*2,dp[i-1][1]+m+1)+1;

    dp[i][1]=min(dp[i-1][1]+(m+1-l[i-1])*2,dp[i-1][0]+m+1)+1;

    然后dp递推到需要关灯的最高层即可(如果那一层以上再没有需要关的灯即为最高层)。最高层的移动不需要再回来,只需要关灯就行。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 char a[20][105];
 5 int l[20],r[20];
 6 int dp[20][2];
 7 int main() {
 8     ios_base::sync_with_stdio(0);
 9     cin.tie(0);
10     int n,m;
11     memset(a,'0',sizeof(a));
12     memset(l,0,sizeof(l));
13     memset(r,0,sizeof(r));
14     memset(dp,0,sizeof(0));
15     cin>>n>>m;
16     for(int i=n;i>=1;i--){
17         for(int j=0;j<=m+1;j++){
18             cin>>a[i][j];
19             if(a[i][j]=='1'){
20                 r[i]=j;
21                 if(l[i]==0){
22                     l[i]=j;
23                 }
24             }
25         }
26     }
27     int high=n;
28     for(int i=n;i>0;i--){
29         if(l[i]==0&&r[i]==0){
30             high--;
31         }
32         else break;
33     }
34     dp[1][0]=0;
35     dp[1][1]=m+1;
36     for(int i=2;i<=high;i++){
37         if(l[i-1]==0&&r[i-1]==0){
38             dp[i][0]=min(dp[i-1][0],dp[i-1][1]+m+1)+1;
39             dp[i][1]=min(dp[i-1][1],dp[i-1][0]+m+1)+1;
40         }
41         else {
42             dp[i][0]=min(dp[i-1][0]+r[i-1]*2,dp[i-1][1]+m+1)+1;
43             dp[i][1]=min(dp[i-1][1]+(m+1-l[i-1])*2,dp[i-1][0]+m+1)+1;
44         }
45     }
46     int result;
47     result=min(dp[high][0]+r[high],dp[high][1]+(m+1-l[high]));
48     cout<<result<<endl;
49 
50 
51 return 0;
52 }
View Code

 

posted @ 2017-06-02 09:24  BadboyQAQ  阅读(139)  评论(0编辑  收藏  举报