加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

HDU 3865 A Hard Journey 2011 Multi-University Training Contest 3 Host by BIT

(2011-07-20 10:12:44)
标签:

hdu

3865

a

hard

journey

it

分类: 动态规划

题目描述:
给你n*n的大格子,每个大格子里面有m*m个小格子,每个小格子里面是0或者1.
额。。。描述起来好麻烦,自己看题吧。。。
解题报告:
dp[i][j][0]表示到达并消灭完ij大格子后面向下的最小花费。
dp[i][j][1]表示到达并消灭完ij大格子后面向右的最小花费。
need[i][j][0]表示横扫ij大格子的花费。
need[i][j][1]表示纵扫ij大格子的花费。
small[i][j]表示通过横红转换一次后消灭ij大格子的花费(对每个大格子二分匹配就能得到)

那么i,j可以由dp[i - 1][j][0]和dp[i][j - 1][1]转移过来。
对于dp[i - 1][j][0]:
dp[i][j][0] = min(dp[i][j][0], need[i][j][0], need[i][j][1] + q + q, small[i][j] + q + q);
dp[i][j][1] = min(dp[i][j][1], need[i][j][0] + q, need[i][j][1] + q, small[i][j] + q);
比较容易理解。
对于dp[i - 1][j][1]:一样。
写的比较麻烦,最好等看解题报告标称吧。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int x[20][20][15][15], n, m, p, q, need[20][20][2], small[20][20];
int dp[20][20][2], match[20], g[20][20];
bool vst[20], equ[20][20];
int find(int u, int m)
{
    for(int i = 0; i < m; i++)
        if (!vst[i] && g[u][i])
        {
            vst[i] = 1;
            if (match[i] == -1 || find(match[i], m) == 1)
            {
                match[i] = u;
                return 1;
            }
        }
    return 0;
}
int solve(int n)
{
    memset(match, -1, sizeof(match));
    int ans = 0;
    for(int i = 0; i < n; i++)
    {
        memset(vst, 0, sizeof(vst));
        ans += find(i, n);
    }
    return ans;
}
int main()
{
    while(scanf("%d%d%d%d", &n, &m, &p, &q) != EOF)
    {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                for(int i2 = 0; i2 < m; i2++)
                    for(int j2 = 0; j2 < m; j2++)
                        scanf("%d", &x[i][j][i2][j2]);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                for(int i2 = 0; i2 < m; i2++)
                    for(int j2 = 0; j2 < m; j2++)
                    {
                        if (x[i][j][i2][j2]) g[i2][j2] = 1;
                        else g[i2][j2] = 0;
                    }
                small[i][j] = solve(m) * p;
            }
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                need[i][j][0] = need[i][j][1] = 0;
                dp[i][j][0] = dp[i][j][1] = 0x7fffffff;
                for(int i2 = 0; i2 < m; i2++)
                {
                    bool flag = false;
                    for(int j2 = 0; j2 < m; j2++)
                        if (x[i][j][i2][j2])
                        {flag = true; break;}
                    need[i][j][0] += flag;
                }
                need[i][j][0] *= p;
                for(int j2 = 0; j2 < m; j2++)
                {
                    bool flag = false;
                    for(int i2 = 0; i2 < m; i2++)
                        if (x[i][j][i2][j2])
                        {flag = true; break;}
                    need[i][j][1] += flag;
                }
                need[i][j][1] *= p;
                if (small[i][j] < need[i][j][0] && small[i][j] < need[i][j][1])
                    equ[i][j] = true;
                else equ[i][j] = false;
            }
        dp[0][0][0] = min(need[0][0][0], need[0][0][1] + q);
        if (equ[0][0]) dp[0][0][0] = min(dp[0][0][0], small[0][0] + q);
        dp[0][0][1] = min(need[0][0][1], need[0][0][0] + q);
        if (equ[0][0]) dp[0][0][1] = min(dp[0][0][1], small[0][0] + q);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                int tmpa, tmpb;
                tmpa = i - 1; tmpb = j;
                if (tmpa >= 0 && tmpa < n && tmpb >= 0 && tmpb < n)
                {
                    int val = dp[tmpa][tmpb][0];
                    int val1 = min(need[i][j][0], need[i][j][1] + q + q);
                    if (equ[i][j]) val1 = min(val1, small[i][j] + q + q);
                    int val2 = min(need[i][j][0] + q, need[i][j][1] + q);
                    if (equ[i][j]) val2 = min(val2, small[i][j] + q);
                    dp[i][j][0] = min(dp[i][j][0], val + val1);
                    dp[i][j][1] = min(dp[i][j][1], val + val2);
                }
                tmpa = i; tmpb = j - 1;
                if (tmpa >= 0 && tmpa < n && tmpb >= 0 && tmpb < n)
                {
                    int val = dp[tmpa][tmpb][1];
                    int val1 = min(need[i][j][1], need[i][j][0] + q + q);
                    if (equ[i][j]) val1 = min(val1, small[i][j] + q + q);
                    int val2 = min(need[i][j][1] + q, need[i][j][0] + q);
                    if (equ[i][j]) val2 = min(val2, small[i][j] + q);
                    dp[i][j][1] = min(dp[i][j][1], val + val1);
                    dp[i][j][0] = min(dp[i][j][0], val + val2);
                }
            }
        printf("%d\n", min(dp[n - 1][n - 1][0], dp[n - 1][n - 1][1]));

    }
    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有