AcWing 276. I-区域

题目超链接
题意
中文题目没啥好说的
首先得知道这是一个dp题,然后再求解,至于怎么知道,还是写题少,菜鸟的悲伤,呜呜呜。

知道是dp后,接下来就是分析了,对于左边分析,肯定是先扩张,然后可能会缩减,而且一旦缩减就不会在扩张了,这样是吧为了保证图形是凸型,
对于右边也是一样的,然后就是看怎么保证是扩张还是缩减了,那么就要知道前一行的某个状态的l到r的状态,然后在本状态再根据是扩张还是缩减
来定义本状态的l和r的值。所以就有下面几个需要维护的:到第几行了,有多少个格子了,本状态的l,本状态的r,左边的扩张还是缩减,右边的扩张还是缩减。

然后就是状态转移方程了
#include <algorithm>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>
#define ll long long int
#define ms(a, b) memset(a, b, sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define se second
#define ull unsigned long long
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define endl "\n"
#define bug cout << "----acac----" << endl;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
const int maxn = 5e5 + 10;
const int maxm = 1e3 + 50;
const double eps = 1e-8;
const ll inf = 0x3f3f3f3f;
const ll lnf = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1);
const ll mod = 1e9 + 7;
int n, m, k;
int a[20][20];
int dp[16][16 * 16][16][16][2][2];
struct node
{
    int i, j, l, r, x, y;
} pre[16][16*16][16][16][2][2];
void print(node A)
{
    if(A.j==0)
        return;
    print(pre[A.i][A.j][A.l][A.r][A.x][A.y]);
    for (int i = A.l; i <= A.r;i++)
    {
        cout << A.i << " " << i << endl;
    }
}
int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <= m;j++)
        {
            cin >> a[i][j];
            a[i][j] += a[i][j - 1];
        }
    }
    int ans = 0;
    node t;
    for (int i = 1; i <= n;i++)
    {
        for (int j = 1; j <= k;j++)
        {
            for (int l = 1; l <= m;l++)
            {
                for (int r = l; r <= m;r++)
                {
                    if(j<(r-l+1))
                        continue;
                    //左边扩张,右边也扩张;
                    for (int l1 = l; l1 <= r;l1++)
                    {
                        for (int r1 = l1; r1 <= r;r1++)
                        {
                            int &u = dp[i][j][l][r][0][0];
                            int v = dp[i - 1][j - (r - l + 1)][l1][r1][0][0] + a[i][r] - a[i][l - 1];
                            if(u<v)
                            {
                                pre[i][j][l][r][0][0] = {i - 1, j - (r - l + 1), l1, r1, 0, 0};
                                u = v;
                            }
                        }
                    }

                    //左边扩张,右边收缩
                    for (int l1 = l; l1 <= r;l1++)
                    {
                        for (int r1 = r; r1 <= m;r1++)
                        {
                            for (int y = 0; y <= 1;y++)
                            {
                                int &u = dp[i][j][l][r][0][1];
                                int v = dp[i - 1][j - (r - l + 1)][l1][r1][0][y] + a[i][r] - a[i][l - 1];
                                if(u<v)
                                {
                                    pre[i][j][l][r][0][1] = {i - 1, j - (r - l + 1), l1, r1, 0, y};
                                    u = v;
                                }
                            }
                        }
                    }

                    //左边收缩,右边扩张
                    for (int l1 = 1; l1 <= l;l1++)
                    {
                        for (int r1 = l; r1 <= r;r1++)
                        {
                            for (int x = 0; x <= 1;x++)
                            {
                                int &u = dp[i][j][l][r][1][0];
                                int v = dp[i - 1][j - (r - l + 1)][l1][r1][x][0] + a[i][r] - a[i][l - 1];
                                if(u<v)
                                {
                                    pre[i][j][l][r][1][0] = {i - 1, j - (r - l + 1), l1, r1, x, 0};
                                    u = v;
                                }
                            }
                        }
                    }

                    //左边收缩,右边也收缩
                    for (int l1 = 1; l1 <= l;l1++)
                    {
                        for (int r1 = r; r1 <= m;r1++)
                        {
                            for (int x = 0; x <= 1;x++)
                            {
                                for (int y = 0; y <= 1;y++)
                                {
                                    int &u = dp[i][j][l][r][1][1];
                                    int v = dp[i - 1][j - (r - l + 1)][l1][r1][x][y] + a[i][r] - a[i][l - 1];
                                    if(u<v)
                                    {
                                        pre[i][j][l][r][1][1] = {i - 1, j - (r - l + 1), l1, r1, x, y};
                                        u = v;
                                    }
                                }
                            }
                        }
                    }

                    if(j==k)
                    {
                        for (int x = 0; x <= 1;x++)
                        {
                            for (int y = 0; y <= 1;y++)
                            {
                                if(ans<dp[i][j][l][r][x][y])
                                {
                                    ans = dp[i][j][l][r][x][y];
                                    t = {i, j, l, r, x, y};
                                }
                                
                            }
                        }
                    }
                    
                }
            }
        }
    }
    cout << "Oil : " << ans << endl;
    print(t);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值