CodeForces - 812B Sagheer, the Hausmeister 搜索 dp

题意:给你n行长度为m的01串(n<15,m<100) 。每次只能走一步,要将所有的1变为零,问最少的步数,注意从左下角开始,每次要将一层清完才能走到上一层,每次只有在第一列或者最后一列才能往上走一层,否则只能左右移动。

题解:由于清完当前层才能继续上一层,所以必然存在一个递推关系。先递推预处理,然后输出ans即可。用far来存最远的那个1,如果这层没有1,假设有一个,令其距离为1

具体看代码注释吧。

坑:没考虑没有1以及只有1层的情况

 

 

#define  _CRT_SECURE_NO_WARNINGS
#include<cstdio>  
#include<algorithm>  
#include<iostream>
#include<string>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
int m, n, len;
int dp[20][2];//清完i层回到最左0右1 所需的min
int far[20][2];//每层楼离左0右1 最远的灯
int no[20];
int main() {
    while (cin >> n >> m) {
        for (int i = 1; i <= n; i++) {//从顶层开始输入
            string s;
            cin >> s;
            len = s.length();
            int j;
            int ok = 0;
            for (j = 1; j < len - 1; j++) if (s[j] == '1') { far[n + 1 - i][1] = len - j; break; }

            for (j = len - 1; j > 0; j--)if (s[j] == '1') { far[n + 1 - i][0] = j + 1; break; }
            for (j = 0; j < len; j++) { if (s[j] == '1') ok = 1; }
            if (ok == 0)far[n + 1 - i][0] = 1, far[n + 1 - i][1] = 1, no[n + 1 - i] = 1;
        }
        //如果某层没灯+1跳过:
        if (no[1]) far[1][0] = 1;//floor 1 no lamp
        dp[1][1] = len - 1; dp[1][0] = far[1][0] * 2 - 2;//wa这儿了,忘记考虑只有1层,应该改far
        for (int i = 2; i <= n; i++) {
            for (int j = 0; j <= 1; j++)dp[i][j] = maxn;
            dp[i][0] = min(max(0, dp[i - 1][0] + far[i][0] * 2 - 1), dp[i - 1][1] + len);
            dp[i][1] = min(max(0, dp[i - 1][1] + far[i][1] * 2 - 1), dp[i - 1][0] + len);
        }

        //1st floor start from left,
        int k = n;
        while (no[k])k--;

        int ans = min(dp[k - 1][0] + far[k][0], dp[k - 1][1] + far[k][1]);
        //1层
        if (k == 1) {
            far[1][0]--; ans = far[1][0];
        }
        cout << ans << endl;
    }
    cin >> n;
}

 

 

 

posted @ 2018-03-17 22:26  SuuTTT  阅读(196)  评论(0编辑  收藏  举报