Collegiate Programming Contest 2020 @ MUST Problem D

UVA 1629 Cake slicing

Answer key by ZhangXiubo

Personal blog : coldtea.tech

在这里插入图片描述

Key Point :

DP
Recursion
Sub-question

Why DP?

Every piece of cake has a similar state(Length and width, number of cherries)
Every state can transfer to another state, and with the process of the transfer, you can find the minimize length of cutting.

How to DP?

Firstly, we need to find the endding state, we can easily get if the number of cheeries on a piece of cake is one means the length of this piece of cake is 0.
then a piece of cake if is organized by two piece of cakes, I mean , you can get the the two piece of cakes by cutting this piece (emmmm we easily set it crosscut ). If this piece of cake left point is L , right point is R. The cutting worth (r-l) obviously.
在这里插入图片描述
在这里插入图片描述
You need to traverse all horizontal and vertical cuts at every step。
If you set upbound u , downbound d, leftbound l, right bound r,you will get the DP transfer formulars.
for (int i = u + 1; i <= d; i++)
{
ans = min(ans, DP(u, i, l, r) + DP(i, d, l, r) + r - l);// interaion all the Upright
}
for (int i = l + 1; i <= r; i++)
{
ans = min(ans, DP(u, d, l, i) + DP(u, d, i, r) + d - u);
//interation all the Sideways
}

Memory search

If you always play fib sequences and use recursion to handle it , you will find the programme will be unbearably slow.The reason is you did plenty of repeated work.
But you can open an extra array to store what you have calculated .
If you need to call it ,you don’t need to calculate again but to load from your array.

code

#include<bits/stdc++.h>
#define ios std::ios::sync_with_stdio(false) //close synchronize
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 20 + 4;
int dp[maxn][maxn][maxn][maxn]; present upbound u , downbound d, leftbound l, right bound r.
int n, m, k;
int cherry[maxn][maxn];//cheery laocation
int sum_cherry(int u, int d, int l, int r)// present upbound u , downbound d, leftbound l, right bound r.
{
    int ans = 0;
    for (int i = u + 1; i <= d; i++)
    {
        for (int j = l + 1; j <= r; j++)
        {
            if (cherry[i][j] == 1)
                ans++;
            if (ans == 2)return ans;//if the number>=2 we should take them out
        }
    }
    return ans;
}

int DP(int u, int d, int l, int r)
{
    int& ans = dp[u][d][l][r];
    if (ans != -1)
        return dp[u][d][l][r];//memery search
    int tot = sum_cherry(u, d, l, r);
    if (tot == 0)return ans = INF;//
    if (tot == 1)return ans = 0;//if last is one return 0
    ans = INF;
    for (int i = u + 1; i <= d; i++)//
    {
        ans = min(ans, DP(u, i, l, r) + DP(i, d, l, r) + r - l);// interaion all the Upright 
    }
    for (int i = l + 1; i <= r; i++)
    {
        ans = min(ans, DP(u, d, l, i) + DP(u, d, i, r) + d - u);//interation all the Sideways
    }
    return ans;
}

int main()
{
    ios;
    int index = 1;
    while (cin>>n>>m>>k)
    {
        int u; int v;
        memset(cherry, 0, sizeof(cherry));
        for (int i = 0; i < k; i++)
        {
            cin >> u >> v;
            cherry[u][v] = 1;//that point has one cherry
        }
        memset(dp, -1, sizeof(dp));
        int ans = DP(0, n, 0, m);
        cout << "Case " << index++ << ": " << ans << "\n";
        
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值