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

【题解】ZJOI2013蚂蚁寻路

时间:2018-05-01 23:39:17      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:namespace   clu   复杂   图形   void   zjoi   int   mes   保存   

  这题强呀……打了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蚂蚁寻路

标签:namespace   clu   复杂   图形   void   zjoi   int   mes   保存   

原文地址:https://www.cnblogs.com/twilight-sx/p/8977424.html

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