uva 1629

点击打开链接题意:给一个由方格矩形,有的方格里面有樱桃。你的任务是沿着方格线进行切割,要求只能直切不能拐弯,使得每个矩形里有且只有一个樱桃。每切一刀的长度是,线的长度,求最小的长度。

这一题,一开始不知道怎么做,我一看题解,大部分都是暴力。这一题暴力的关键在于,控制好切割边界。因为输入的是方格,所以我们可以加一条辅助线。

/**
TASK: milk3
ID: DickensTone
LANG: C++
**/
#include
#include
#include
using namespace std;
int n, m, k;
const int inf = (20 + 3) * (20 + 3);
int dp[20 + 5][20 + 5][20 + 5][20 + 5];
bool vis[20 + 5][20 + 5];
int check(int lx, int ly, int rx, int ry)
{
    int cnt = 0;
    for(int i = lx + 1; i <= rx; i++)
        for(int j = ly + 1; j <= ry; j++)
        {
            if(vis[i][j]) cnt++;
            if(cnt >= 2) return 2;
        }
    return cnt;
}
int DP(int lx, int ly, int rx, int ry)//记忆化搜索
{
    int &ret = dp[lx][ly][rx][ry];
    if(ret != -1) return ret;
    int num = check(lx, ly, rx, ry);
    if(num == 1) return ret = 0;
    if(!num) return ret = inf;
    ret = inf;
    for(int s = lx + 1; s < rx; s++)
    {
        ret = min(ret, DP(lx, ly, s, ry) + DP(s, ly, rx, ry) + ry - ly);
    }
    for(int s = ly + 1; s < ry; s++)
    {
        ret = min(ret, DP(lx, ly, rx, s) + DP(lx, s, rx, ry) + rx - lx);
    }
    return ret;
}
int main()
{
    //freopen("milk3.in", "r", stdin);
    //freopen("milk3.out", "w", stdout);
    int kase = 1;
    while(scanf("%d%d%d", &n, &m, &k) == 3)
    {
        memset(dp, -1, sizeof(dp));
        memset(vis, 0, sizeof(vis));
        for(int i = 0; i < k; i++)
        {
            int t1, t2;
            scanf("%d%d", &t1, &t2);
            vis[t1][t2] = 1;
        }
        int ans = DP(0, 0, n, m);//因为需要方格之间的线,所以得从零开始,需要自己画图理解一下
        printf("Case %d: %d\n", kase++, ans);
    }
    return 0;
}


你可能感兴趣的:(uva)