题解ZJOI2013蚂蚁寻路

Posted Twilight_Sx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解ZJOI2013蚂蚁寻路相关的知识,希望对你有一定的参考价值。

  这题强呀……打了10+30暴力之后苦想1h并不会做……于是去看题解。看题解的时候又莫名各种看错,结果看了好久才懂……记录一下血泪史吧。

  这题不难发现走出来的图形就是一个高低高低的城堡型图案,命名为高峰跟低谷的话就是一共有k个低谷和k + 1个高峰,且交替出现。发现其实这个图形是由2 * k + 1个矩形所构成的,我们考虑将这样许多矩形看做转移的方向:f[i][j][p][h]代表以点(i, j)为左下角,当前枚举到的是第p个矩形,且高度为(i - h + 1)所能获得的最大权值。

  转移方程:

    \(f[i][j][p][h] = \left \{ f[i][j - 1][p][h], f[i][j - 1][p][h‘]] \right \} + s[j][i] - s[j][h - 1]; \)

  其中第一部分代表和j - 1处于同一个矩形当中,第二部分则表示根据p的奇偶性选择<h或>h的转移。第二部分如果枚举,则复杂度太高了难以承受,所以用另一个数组g来保存,追加一维0/1来表示是>还是<中的最大值。期间有一个让我比较纠结的地方,就是

    \( ans = max(f[i][j][k][i], g[i][j][k][i][0]); \)

  然后发现其实 i 这一维是没有参与转移的,所以将这一维去掉,节约空间。

  起初并没有很理解为什么要将前一部分考虑进来。当高度等于i,不是说明这是一个低谷吗?为什么会符合条件呢?但其实有一种情况下是可以的:当没有低谷的时候,这样是一个符合条件的解。2d的dp做的太少了,要多多加油呀ヾ(????)?"

#include <bits/stdc++.h>
using namespace std;
#define INF 999999999
#define maxn 105
int n, m, k, ans = -INF, sum[maxn][maxn];
int f[maxn][maxn][maxn], g[maxn][maxn][maxn][2];

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); }
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar();
    return x * k;
}
 
void work()
{
    for(int p = 1; p <= k; p ++)
        for(int h = 1; h <= n; h ++)
        {
            f[0][p][h] = -INF;
            g[0][p][h][0] = g[0][p][h][1] = -INF;
        }
        
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
        {
            for(int p = 1; p <= k; p ++)
            {
                for(int h = 1; h <= i; h ++)
                {
                    f[j][p][h] = max(f[j - 1][p][h], g[j - 1][p - 1][h][p % 2]);
                    f[j][p][h] += sum[j][i] - sum[j][h - 1];
                }
                g[j][p][1][0] = -INF;
                for(int h = 2; h <= i; h ++)
                    g[j][p][h][0] = max(g[j][p][h - 1][0], f[j][p][h - 1]);
                g[j][p][i][1] = -INF;
                for(int h = i - 1; h >= 1; h --)
                    g[j][p][h][1] = max(g[j][p][h + 1][1], f[j][p][h + 1]);
            }
            ans = max(ans, max(f[j][k][i], g[j][k][i][0]));
        }
}

int main()
{
    n = read(), m = read(), k = read();
    k = k * 2 + 1;
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= m; j ++)
        {
            int t = read();
            sum[j][i] += sum[j][i - 1] + t;
        }
    work();
    printf("%d\n", ans);
    return 0;
}

 

以上是关于题解ZJOI2013蚂蚁寻路的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3111: [Zjoi2013]蚂蚁寻路

Luogu2586 [ZJOI2008]杀蚂蚁 ---- 模拟

[ZJOI2008]杀蚂蚁 Solution

P2586 [ZJOI2008]杀蚂蚁

BZOJ3110 [ZJOI2013] K大数查询(加强数据)

[ZJOI2008]杀蚂蚁antbuster