[swustoj 1095] 挖金子

挖金子(1095)

题目描述

你在一个N*M的区域中,一开始在(1,1)的位置,每个位置有可能有金子,也有可能不能到达,也有可能有传送门。你只能往右或者下走,不能走出这个区域。当你位于传送门时,传送门你可以选择使用或者不使用,使用的次数无限,若使用则传送到传送门指定的位置。每个位置的金子你可以拿走它,问最后你最多能够拿走多少金子。

输入

首先测试数据组数T。

对于每组测试数据,先输入两个整数N,M(2<=N,M<=40)。

接下来是一个N*M的矩阵,表示每个位置的内容X,若0<=X<=9,表示该位置的金子个数为X,若X为‘*‘,表示该位置有一个传送门,若X为‘#‘,表示该位置不可到达。

假设传送门的个数为K个,接下来K行,每行两个整数x,y(0<=x<n,0<=y<m),依次表示每个传送门传送的位置,顺序是从第一行开始从上到下扫描,每一行从左往右扫描。

输出

对于每组数据,输出能够得到的最多的金子的个数。

样例输入

1
2 2
11
1*
0 0

样例输出

3

好累、- -

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1610

int n,m;
int top;
int bcnt;
int Index;
int dfn[N];
int low[N];
int stack[N];
int belong[N];
bool instack[N];
vector<int> v1[N],v2[N];

int tn,k;
int dp[N];
int gold[N];
int mpt[45][45];
int num[45][45];
pair<int,int> p[N];
int dir[2][2]={1,0,0,1};

void init1()
{
    k=tn=0;
    for(int i=0;i<n*m;i++){
        v1[i].clear();
        v2[i].clear();
    }
}
void init2()
{
    top=-1;
    bcnt=Index=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(instack,0,sizeof(instack));
}
void tarjan(int u,int pre)
{
    int son=0,v;
    dfn[u]=low[u]=++Index;
    instack[u]=1;
    stack[++top]=u;
    for(int i=0;i<v1[u].size();i++){
        v=v1[u][i];
        if(!dfn[v]){
            son++;
            tarjan(v,u);
            if(low[u]>low[v]) low[u]=low[v];
        }
        else if(instack[v] && low[u]>dfn[v])
            low[u]=dfn[v];
    }
    if(dfn[u]==low[u]){
        bcnt++;
        do{
            v=stack[top--];
            instack[v]=0;
            belong[v]=bcnt;
        }while(v!=u);
    }
}
int dfs(int u)
{
    if(dp[u]!=-1) return dp[u];
    dp[u]=gold[u];
    for(int i=0;i<v2[u].size();i++){
        int v=v2[u][i];
        dp[u]=max(dp[u],gold[u]+dfs(v));
    }
    return dp[u];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init1();
        for(int i=0;i<n;i++){ //编号
            for(int j=0;j<m;j++){
                scanf(" %c",&mpt[i][j]);
                if(mpt[i][j]!=‘#‘) num[i][j]=tn++;
                if(mpt[i][j]==‘*‘) p[k++]=make_pair(i,j);
            }
        }
        for(int i=0;i<k;i++){ //建图1
            int tx,ty;
            scanf("%d%d",&tx,&ty);
            v1[num[p[i].first][p[i].second]].push_back(num[tx][ty]);
        }
        for(int i=0;i<n;i++){ //建图2
            for(int j=0;j<m;j++){
                if(mpt[i][j]==‘#‘) continue;
                for(int k=0;k<2;k++){
                    int tx=i+dir[k][0];
                    int ty=j+dir[k][1];
                    if(tx>=0 && tx<n && ty>=0 && ty<m && mpt[tx][ty]!=‘#‘)
                        v1[num[i][j]].push_back(num[tx][ty]);
                }
            }
        }
        init2();
        for(int i=0;i<tn;i++){ //Tarjan
            if(!dfn[i]) tarjan(i,i);
        }
        memset(gold,0,sizeof(gold));
        for(int i=0;i<n;i++){ //计算金币
            for(int j=0;j<m;j++){
                if(mpt[i][j]>=‘0‘ && mpt[i][j]<=‘9‘) gold[belong[num[i][j]]]+=mpt[i][j]-‘0‘;
            }
        }
        for(int i=0;i<tn;i++){ //缩点建图
            for(int j=0;j<v1[i].size();j++){
                if(belong[i]!=belong[v1[i][j]])
                    v2[belong[i]].push_back(belong[v1[i][j]]);
            }
        }
        memset(dp,-1,sizeof(dp));
        int ans=dfs(belong[0]); //记忆化搜索
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-17 00:41:26

[swustoj 1095] 挖金子的相关文章

微信小程序源码下载(200多个)

微信小程序源码下载汇总,点击标题进入对应的微信小程序下载页面. 最新 demo源码(点击标题进入帖子下载) 描述 1 微信小程序 会议室预定小程序 微信小程序 会议室预定小程序**** 本内容被作者隐藏 **** 2 微信小程序-双人五子棋小游戏 微信小程序-双人五子棋小游戏**** 本内容被作者隐藏 **** 3 打卡签到小程序 用微信小程序实现的一个简单的打卡签到的小程序拒绝 4 微信小程序---左滑删除 微信小程序---左滑删除**** 本内容被作者隐藏 **** 5 一个借钱的记事本的微

金矿模型看动归(PASCAL版)

原文地址:http://www.cnblogs.com/SDJL/archive/2008/08/22/1274312.html{PASCAL语言} 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出

下载零基础数据分析与挖掘R语言实战课程(R语言)

随着大数据在各行业的落地生根和蓬勃发展,能从数据中挖金子的数据分析人员越来越宝贝,于是很多的程序员都想转行到数据分析,挖掘技术哪家强?当然是R语言了,R语言的火热程度,从TIOBE上编程语言排名情况可见一斑.于是善于学习的程序员们开始了R语言的学习之旅.对于有其他语言背景的程序员来说,学习R的语法小菜一碟,因为它的语法的确太简单了,甚至有的同学说1周就能掌握R语言,的确如此.但是之后呢?……好像进行不下去了!死记硬背记住了两个分析模型却不明其意,输出结果如同天书不会解读,各种参数全部使用缺省值,

动态规划专题 01背包问题详解【转】

对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢! 初识动态规划 经典的01背包问题是这样的: 有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值,问当从这n个物品中选择多个物品放

经典算法之动态规划

动态规划让我纠结了好一阵子,背包问题让我觉得不知道怎么入手,到处搜索都是一条条的公式,晦涩难懂.偶然间发现了一个博客写的动态规划解释非常的好,虽然还没完全随心所用,但是总算是入门了,下列内容为转载,附上原地址:http://www.cnblogs.com/sdjl/articles/1274312.html 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动

通过金矿模型介绍动态规划

对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢! ----第一节----初识动态规划-------- 经典的01背包问题是这样的: 有一个包和n个物品,包的容量为m,每个物品都有各自的体积和

非常特别的一个动态规划新手教程

今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的解说很不一样,令我眼前一亮,于是转载一下下--- (说明一下,本人很痛恨教材公式定理漫天飞,实际的解说却讲得很枯涩难懂,这样的中国式的教育已经延绵了几千年了,如今中国的教材还是这个样子,讲清楚些明确些就那么难么?高中有个老师讲的一句话一直认为很有道理:"教得会天才不是真本事,能把博士生的东西讲到小学生都会用那才是真水平.") 附上原文地址: http://www.cnblogs.com/sdjl/articles/1

动态规划入门

通过金矿模型介绍动态规划 点击下载01背包测试数据.rar 对于动态规划,每个刚接触的人都需要一段时间来理解,特别是第一次接触的时候总是想不通为什么这种方法可行,这篇文章就是为了帮助大家理解动态规划,并通过讲解基本的01背包问题来引导读者如何去思考动态规划.本文力求通俗易懂,无异性,不让读者感到迷惑,引导读者去思考,所以如果你在阅读中发现有不通顺的地方,让你产生错误理解的地方,让你难得读懂的地方,请跟贴指出,谢谢! ----第一节----初识动态规划-------- 经典的01背包问题是这样的:

[转]很特别的一个动态规划入门教程

很特别的一个动态规划入门教程 今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下--- (说明一下,本人非常痛恨教材公式定理漫天飞,实际的讲解却讲得非常枯涩难懂,这种中国式的教育已经延绵了几千年了,现在中国的教材还是这个样子,讲清楚 些明白些就那么难么?高中有个老师讲的一句话一直觉得很有道理:“教得会天才不是真本事,能把博士生的东西讲到小学生都会用那才是真水平.”) 附上原文地址: http://www.cnblogs.com/sd