ACM学习历程—Hihocoder 1290 Demo Day(动态规划)

http://hihocoder.com/problemset/problem/1290

这题是这次微软笔试的第三题,过的人比第一题少一点,这题一眼看过去就是动态规划,不过转移方程貌似不是很简单,调试了比较久才正确,不过好在是1A,但是最后只留了一个小时多一点给B题,也导致了B题最后也没能AC掉。首先状态是很好确定的p[i][j][k]表示走到第i行第j个格子时,方向是k的情况下的最小改变格子数目。(k from {0, 1})而且由于只有往下和往右走,所以中间过程进行转移时改变的格子不会影响后续过程中的转移,所以只需要分析p[i][j][0]和p[i][j][1]分别怎么由上面和左边的格子得到。情况比较多,基本上在代码里就可以看明白,不过需要对几处边界条件判断一下,比如第一列无法由左边格子得到,第一行无法由上面的格子得到,还有就是向下和向右撞到边界的时候。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

int n, m;
char str[105][105];
int p[105][105][2];

void input()
{
    for (int i = 0; i < n; ++i)
        scanf("%s", str[i]);
    memset(p, -1, sizeof(p));
}

void work()
{
    int t;
    if (str[0][0] == '.') p[0][0][0] = 0;
    else p[0][0][0] = 1;
    if (m == 1 || str[0][1] == 'b') p[0][0][1] = 0;
    else p[0][0][1] = 1;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            if (i == 0 && j == 0) continue;
            if (j == 0)
            {
                //left
                if (i+1 == n || str[i+1][j] == 'b')
                    p[i][j][0] = p[i-1][j][1];
                else
                    p[i][j][0] = p[i-1][j][1]+1;
                if (str[i][j] == 'b') p[i][j][0]++;

                //bottom
                p[i][j][1] = p[i-1][j][1];
                if (str[i][j] == 'b') p[i][j][1]++;
            }
            else
            {
                //left
                p[i][j][0] = p[i][j-1][0];
                if (str[i][j] == 'b') p[i][j][0]++;
                if (i > 0)
                {
                    t = p[i-1][j][1];
                    if (str[i][j] == 'b') t++;
                    if (i+1 == n || str[i+1][j] == 'b')
                        p[i][j][0] = min(p[i][j][0], t);
                    else
                        p[i][j][0] = min(p[i][j][0], t+1);
                }

                //bottom
                p[i][j][1] = p[i][j-1][0];
                if (str[i][j] == 'b') p[i][j][1]++;
                if (!(j+1 == m || str[i][j+1] == 'b'))
                    p[i][j][1]++;
                if (i > 0)
                {
                    t= p[i-1][j][1];
                    if (str[i][j] == 'b') t++;
                    p[i][j][1] = min(p[i][j][1], t);
                }
            }
        }
    }
    printf("%d\n", min(p[n-1][m-1][0], p[n-1][m-1][1]));
}

int main()
{
    //freopen("test.in", "r", stdin);
    while (scanf("%d%d", &n, &m) != EOF)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

posted on 2016-04-09 13:24  AndyQsmart  阅读(585)  评论(5编辑  收藏  举报

导航