码迷,mamicode.com
首页 > 其他好文 > 详细

蓝桥杯:地宫取宝

时间:2015-04-07 09:37:54      阅读:318      评论:0      收藏:0      [点我收藏+]

标签:

蓝桥杯:地宫取宝

蓝桥杯:地宫取宝

标题:地宫取宝

X 国王有一个地宫宝库。是 n x m 个格子的矩阵。每个格子放一件宝贝。每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k 件宝贝。

【数据格式】

输入一行 3 个整数,用空格分开:n m k (1<=n,m<=50, 1<=k<=12)

接下来有 n 行数据,每行有 m 个整数 Ci (0<=Ci<=12)代表这个格子上的宝物的价值

要求输出一个整数,表示正好取 k 个宝贝的行动方案数。该数字可能很大,输出它对 1000000007 取模的结果。

例如,输入:
2 2 2
1 2
2 1
程序应该输出:
2

再例如,输入:
2 3 2
1 2 3
2 1 5
程序应该输出:
14

错误的写法

/*
 * CreateTime: 2015-04-06 10:29:05
 */

#include <cstdio>

const int maxn = 80;
int k;
int n;
int m;
int count;
int g[maxn][maxn];

int cur_max;

void dfs(int i, int j, int step) {
    if (i > n || j > m || step > k ) {
        return;
    }
    if (step == k) {
        count++;
    }

    if (g[i][j] > cur_max) {
        int ori_max = cur_max;
        cur_max = g[i][j];
        dfs(i+1, j, step+1);
        dfs(i, j+1, step+1);

        cur_max = ori_max;   // 回溯

        dfs(i+1, j, step);
        dfs(i, j+1, step);
    } else {
        dfs(i+1, j, step);
        dfs(i, j+1, step);
    }
}

int main(void) {
    cur_max = 0;
    n = 2;
    m = 3;
    k = 2;
    count = 0;
    g[1][1] = 1;
    g[1][2] = 2;
    g[1][3] = 3;
    g[2][1] = 2;
    g[2][2] = 1;
    g[2][3] = 5;


    dfs(1, 1, 0);

    printf("%d\n", count);

    return 0;
}

改进后

#include <cstdio>

const int maxn = 80;
int k;
int n;
int m;
int count;
int g[maxn][maxn];

int cur_max;

void dfs(int i, int j, int step) {
    if (i > n || j > m || step > k ) {
        return;
    }
    if (n == i && m == j) {
        if (step == k) {
            count++;
        } else if (step == k-1) {
            if (g[i][j] > cur_max) {
                count++;
            }
        }
        return;
    }

    if (g[i][j] > cur_max) {
        int ori_max = cur_max;
        cur_max = g[i][j];
        dfs(i+1, j, step+1);
        dfs(i, j+1, step+1);

        cur_max = ori_max;   // 回溯

        dfs(i+1, j, step);
        dfs(i, j+1, step);
    } else {
        dfs(i+1, j, step);
        dfs(i, j+1, step);
    }
}

int main(void) {
    cur_max = 0;
    n = 2;
    m = 3;
    k = 2;
    count = 0;
    g[1][1] = 1;
    g[1][2] = 2;
    g[1][3] = 3;
    g[2][1] = 2;
    g[2][2] = 1;
    g[2][3] = 5;


    dfs(1, 1, 0);

    printf("%d\n", count);

    return 0;
}

再次改进

#include <iostream>

using namespace std;

const int maxn = 80;
int k;
int n;
int m;
long long count;
int g[maxn][maxn];

void dfs(int i, int j, int step, int max) {
    if (i > n || j > m || step > k ) {
        return;
    }

    if (i == n && j == m) {
        if (step == k) {
            count++;
        } else if (step == k-1 && max < g[i][j]) {
            count++;
        }
    }

    if (g[i][j] > max) {
        dfs(i+1, j, step+1, g[i][j]);
        dfs(i, j+1, step+1, g[i][j]);
    }
    dfs(i+1, j, step, max);
    dfs(i, j+1, step, max);
}

int main(void) {
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> g[i][j];
        }
    }

    dfs(1, 1, 0, -1);
    cout << count % 1000000007 << endl;

    return 0;
}

用记忆的方法去改进

/*
 * CreateTime: 2015-04-06 10:29:05
 */

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int maxn = 80;
const int mod = 1000000007;
int k;
int n;
int m;
int g[maxn][maxn];
int mem[maxn][maxn][15][15];

int dfs(int i, int j, int step, int max) {
    if (mem[i][j][step][max+1] != -1) {
        return mem[i][j][step][max+1];
    }
    if (i > n || j > m || step > k ) {
        return 0;
    }

    if (i == n && j == m) {
        if (step == k) {
            return mem[i][j][step][max+1] = 1;
        } else if (step == k-1 && max < g[i][j]) {
            return mem[i][j][step][max+1] = 1;
        }
    }

    int s = 0;
    if (g[i][j] > max) {
        s += dfs(i+1, j, step+1, g[i][j]);
        s = s % mod;
        s += dfs(i, j+1, step+1, g[i][j]);
        s = s % mod;
    }
    s += dfs(i+1, j, step, max);
    s = s % mod;
    s += dfs(i, j+1, step, max);
    s = s % mod;
    return mem[i][j][step][max+1] = s;
}

int main(void) {
    memset(mem, -1, sizeof(mem));
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> g[i][j];
        }
    }

    int s = dfs(1, 1, 0, -1);
    cout << s % mod << endl;

    return 0;
}

蓝桥杯:地宫取宝

标签:

原文地址:http://www.cnblogs.com/sunznx/p/4397419.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!