SGU167

恶心的DP啊
题解网上很多,就不说了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define REP(i, a, b) for(int i = (a); i <= (b); ++i)
#define sum(i, l, r) (g[i][r] - g[i][l-1])
#define code(l, r, opl, opr) ((l << 12) + (r << 8) + (opl << 4) + (opr))
#define encode(s) (s >> 12) & 15, (s >> 8) & 15, (s >> 4) & 15, s & 15
using namespace std;

inline int read()
{
    int x = 0, f = 1, t = getchar();
    while(t < 48 || t > 57) t == 45 ? f = -1 : 0, t = getchar();
    while(t > 47 && t < 58) x = (x << 1) + (x << 3) + t - 48, t = getchar();
    return x * f;
}

typedef int Array[16][16][16][2][2][226];

int n, m, k, ans, arow, al, ar, aopl, aopr, g[16][16];
Array f, p;

//op = 0 / left
//op = 1 \ right

void expand(int row, int l, int r, int opl, int opr, int s)
{
    REP(ll, opl == 0 ? 1 : l, r) REP(rr, max(l, ll), opr == 1 ? m : r)
    {
        int opll = (ll == l ? opl : (ll < l ? 0 : 1));
        int oprr = (rr == r ? opr : (rr < r ? 0 : 1));
        int &res = f[row + 1][ll][rr][opll][oprr][s+(rr-ll+1)];
        int tmp = f[row][l][r][opl][opr][s] + sum(row+1, ll, rr);
        if(res < tmp) res = tmp, p[row + 1][ll][rr][opll][oprr][s+(rr-ll+1)] = code(l, r, opl, opr);
    }
}
void write(int row, int l, int r, int opl, int opr, int s)
{
    if(row == 0 || s <= 0) return ;
    int pp = p[row][l][r][opl][opr][s];
    write(row-1, encode(pp), s-(r-l+1));
    REP(i, l, r) printf("%d %d\n", row, i);
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    n = read(), m = read(), k = read();
    REP(i, 1, n) REP(j, 1, m) g[i][j] = g[i][j-1] + read();
    memset(f, -1, sizeof(f));
    REP(row, 1, n) REP(l, 1, m) REP(r, l, m) REP(opl, 0, 1) REP(opr, 0, 1)
    {
        f[row][l][r][opl][opr][r-l+1] = sum(row, l, r);
        REP(s, r-l+1, k)
        {
            int &res = f[row][l][r][opl][opr][s];
            if(res > 0)
            {
                if(row < n) expand(row, l, r, opl, opr, s);
                if(s == k && res > ans) ans = res, arow = row, al = l, ar = r, aopl = opl, aopr = opr;
            }
        }
    }
    printf("Oil : %d\n", ans);
    write(arow, al, ar, aopl, aopr, k);

    #ifndef ONLINE_JUDGE
    fclose(stdin), fclose(stdout);
    #endif
    return 0;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值