ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

3737. 【NOI2014模拟7.11】挖宝藏(treasure)

2022-01-14 20:02:00  阅读:174  来源: 互联网

标签:单位 7.11 int treasure NOI2014 leq 矿工 include 宝藏


Description

“挖矿小子”是一个经典的益智小游戏。玩家需要指挥矿工下地挖掘宝藏,每次矿工可以挖开其左边、右边或下方的格子,不可以挖上方的格子。矿工往下挖矿后就再也不能上来。获得所有宝藏后游戏结束。

这个游戏太简单了,在 \(3 \mathrm{D}\) 版 2048 出现之前若干年,就有人开发出了 \(3 \mathrm{D}\) 版的 “挖矿小
子”。

游戏的地图是一个 \(h \times n \times m\) 的立方体。立方体由上至下共有 \(h\) 层,编号依次为
\(1,2, \ldots, h\),每层是一个 \(n \times m\) 的方阵。你可以假定地面层的编号为 0 。初始时所有单位立
方体 (简称单位) 均有泥土,一些单位有宝藏。挖开单位 \((i, j, k)\) (第 \(i\) 层第 \(j\) 行第 \(k\) 列,\(1 \leq i \leq h, 1 \leq j \leq n, 1 \leq k \leq m\) ) 的泥土消耗的体力为 \(a[i, j, k]\) 。当矿工在单位 \((z, x, y)\)
时,他可以不费体力地获得该单位的宝藏 (如果有的话),同时他可以挖开任一相邻单位(\((z, x-1, y),(z, x+1, y),(z, x, y-1),(z, x, y+1),(z+1, x, y)\))的泥土,如果相邻单位的泥土已经被挖走, 则矿工可以直接到达该单位而不消耗任何体力。矿工不可以到达地图范围之外。和普通版游戏一样, 矿工不可以挖所在位置上方的单位,如果矿工挖开其下方的单位,他会掉落到下一层,并永远不能回到原来所在的层。当矿工获得所有宝藏时,游戏结束,得分为矿工消耗的总体力。

现在你正在玩这个游戏的某一关,在 \(a[i, j, k]\) 和宝藏位置已知的情况下,你需要让你的
矿工顺利地获得所有的宝藏,并使他消耗的体力最少。

Solution

这题是 WC2008 游览计划的加强版,本题中 \(h\) 不再为 1,但我们依旧可以采用同样的方法,用状压 \(\mathrm{DP}\) 来解决此题。

设 \(f_{i,j,k,s}\) 表示到了第 \(i\) 层,在第 \(j\) 行,第 \(k\) 列,宝藏状态为 \(s\)。

先枚举 \(s\) 的子集 \(ss\),转移方程:\(f_{i,j,k,s}=\min(f_{i,j,k,ss}+f_{i,j,k,s-ss}-a_{i,j,k})\)。

然后枚举 \((j,k)\) 周围的单位,转移方程:\(f_{i,j,k,s}=\min(f_{i,x,y,s}+a_{i,j,k})\)。

注意到第 2 个转移方程有后效性,所以用 \(spfa\) 来转移。

至于层与层之间,考虑新建一个节点,表示当前层宝藏全都取完了,然后转移。

Code

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 15
#define inf 0X3f3f3f3f
using namespace std;
struct node
{
    int x,y;
};
queue<node> q;
int h,n,m,x,y,ans=0X3f3f3f3f,mp[N][N][N],cnt[N],bz[N][N][N],f[N][N][N][1<<10],fx[5]={0,0,0,1,-1},fy[5]={0,1,-1,0,0};
bool bj[N][N];
void spfa(int i,int s)
{
    while (!q.empty())
    {
        node u=q.front();q.pop();
        for (int k=1;k<=4;++k)
        {
            int x=u.x+fx[k],y=u.y+fy[k];
            if (x<1||x>n||y<1||y>m) continue;
            if (f[i][x][y][s]>f[i][u.x][u.y][s]+mp[i][x][y])
            {
                f[i][x][y][s]=f[i][u.x][u.y][s]+mp[i][x][y];
                if (!bj[x][y])
                {
                    q.push((node){x,y});
                    bj[x][y]=true;
                }
            }
        }
        bj[u.x][u.y]=false;
    }
}
int main()
{
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    scanf("%d%d%d",&h,&n,&m);
    for (int i=1;i<=h;++i)
        for (int j=1;j<=n;++j)
            for (int k=1;k<=m;++k)
                scanf("%d",&mp[i][j][k]);
    for (int i=1;i<=h;++i)
    {
        scanf("%d",&cnt[i]);
        for (int j=1;j<=cnt[i];++j)
        {
            scanf("%d%d",&x,&y);
            bz[i][x][y]=j;
        }
        if (i>1) ++cnt[i];
    }
    memset(f,0x3f3f3f3f,sizeof(f));
    for (int i=1;i<=h;++i)
    {
        for (int j=1;j<=n;++j)
            for (int k=1;k<=m;++k)
            {
                if (bz[i][j][k]) f[i][j][k][1<<(bz[i][j][k]-1)]=mp[i][j][k];
                else f[i][j][k][0]=mp[i][j][k];
            }
        for (int s=0;s<(1<<cnt[i]);++s)
        {
            for (int j=1;j<=n;++j)
                for (int k=1;k<=m;++k)
                {
                    for (int ss=s;ss;--ss)
                    {
                        if ((ss|s)!=s) continue;
                        f[i][j][k][s]=min(f[i][j][k][s],f[i][j][k][ss]+f[i][j][k][s-ss]-mp[i][j][k]);
                    }
                    if (f[i][j][k][s]<inf) q.push(node{j,k}),bj[j][k]=true;
                }
            spfa(i,s);
            if (s==(1<<cnt[i])-1)
            {
                for (int j=1;j<=n;++j)
                    for (int k=1;k<=m;++k)
                    {
                        if (f[i][j][k][s]>=inf) continue;
                        if (i==h) ans=min(ans,f[i][j][k][s]);
                        else if (bz[i+1][j][k]) f[i+1][j][k][(1<<(cnt[i+1]-1))|(1<<(bz[i+1][j][k]-1))]=f[i][j][k][s]+mp[i+1][j][k];
                        else f[i+1][j][k][1<<(cnt[i+1]-1)]=f[i][j][k][s]+mp[i+1][j][k];
                    }
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

标签:单位,7.11,int,treasure,NOI2014,leq,矿工,include,宝藏
来源: https://www.cnblogs.com/Livingston/p/15803364.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有