挖地雷问题(DAG最长路)

挖地雷问题

(P3.pas/c/cpp)

来源:NOIP1996(提高组)第三题(有改动)

【问题描述】

在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。

当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。

【输入文件】

N:(表示地窖的个数)

   W1,W2,W3,……WN
(表示每个地窖中埋藏的地雷数量)

A12…………… .     A1N

A23…………..A2N

……..

AN-1N

【输出文件】

K1--K2--……….KV            
(挖地雷的顺序)

MAX                          
(挖地雷的数量)

【输入样例】            //////整一个类数字三角形

5

10,8,4,7,6

1 1 1 0

0 0 0

1 1

1

【输出样例】

1->3->4->5

max=27

思路:

dp[ i ]表示 以i为起点的挖到最多的雷数;

dp[ i ]=w[ i ]+max{ dp[ j ]  | (i ,j )通路 };

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define N 210
using namespace std;

int w[N];
int dp[N];

struct node{
    int to;
    int next;
}edge[N*N];

int pre[N];
int path[N];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof dp);
        memset(pre,-1,sizeof pre);
        memset(path,0,sizeof path);
        for(int i=1;i<=n;i++)
            scanf("%d",w+i);
        int v;
        int cnt=0;
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)
            {
                scanf("%d",&v);               //邻接表
                if(v)
                {
                    edge[cnt].to=j;
                    edge[cnt].next=pre[i];
                    pre[i]=cnt++;
                }
            }
        dp[n]=w[n];
        int maxx=0;
        int u;
        int p;
        for(int i=n-1;i>=1;i--)      //dp
        {
            u=pre[i];
            while(u)
            {
                v=edge[u].to;
                if(dp[v]>maxx)
                {
                    maxx=dp[v];
                    p=v;
                }
                u=edge[u].next;
            }
            path[i]=p;             //路<span style="font-family:Times New Roman;">径记录</span>
            dp[i]=maxx+w[i];
        }
        int k=1;
        for(int i=1;i<=n;i++)
            if(dp[i]>dp[k]) k=i;
        maxx=dp[k];
        printf("%d",k);
        k=path[k];
        while(k)
        {
            printf("->%d",k);
            k=path[k];
            //printf("%d",k);
        }
        cout<<endl<<maxx<<endl;
    }
    return 0;
}
时间: 2024-10-18 05:44:16

挖地雷问题(DAG最长路)的相关文章

简单Dp----最长公共子序列,DAG最长路,简单区间DP等

/* uva 111 * 题意: * 顺序有变化的最长公共子序列: * 模板: */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100]; int mu[100]; int Dp[100][100]; int main() { int n,x; scanf("%d", &n

UVA 11324 The Largest Clique (强连通缩点 + DAG最长路)

链接 : http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30726 题意 : 有向图G,求一个最大的点集,使得点集中任意两个节点u和v,满足 要么u可以到达v,要么v可以到达u,或者u和v可以相互到达. 可以强连通缩点成一张DAG,以为每个强连通分量要么选要么不选.求DAG上的最长路 二次建图 用了2种不同的方法,也分别用了记忆花搜索DP和直接递推DP vector建图和记忆化搜索: #include <algorithm

02_嵌套矩形(DAG最长路问题)

来源:刘汝佳<算法竞赛入门经典--训练指南> P60 问题2: 问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它们的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中的条件为:当且仅当a<c,b<d 或者b<c,a<d(相当于把矩形X旋转90 度).选出尽量多的矩形排成一行,使得除了最后一个之外,每一个矩形都可以嵌套在下一个矩形内. 分析:对于本题中的n个矩形,以每个矩形作为一个点,若X矩形能嵌套在Y矩形中,则从X向Y连一条边,题目则变为了在DAG(无回

poj 3249 Test for Job (DAG最长路 记忆化搜索解决)

Test for Job Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 8990   Accepted: 2004 Description Mr.Dog was fired by his company. In order to support his family, he must find a new job as soon as possible. Nowadays, It's hard to have a job

DAG最长路问题 hdu-1224

用DFS+记忆化写了一下,拓扑排序+DP的我还没弄明白.据说Codeforces 721C就是这类题目,因为有费用限制,DFS不太好写,有时间把DP法想明白来. #include <iostream> #include <cstdio> #include <vector> #include <stack> #define LL long long int using namespace std; LL sta[105]; vector<int>

uva 10131 Is Bigger Smarter? dag 最长路 加路径还原

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <climits> #include <cstring> #include <cmath> #include <map> #include <set> #define INF 10000

uva103(最长递增序列,dag上的最长路)

题目的意思是给定k个盒子,每个盒子的维度有n dimension 问最多有多少个盒子能够依次嵌套 但是这个嵌套的规则有点特殊,两个盒子,D = (d1,d2,...dn) ,E = (e1,e2...en) 只要盒子D的任意全排列,小于盒子E,那么就说明 盒子D能放入盒子E中,其实就是将两个盒子的维度排序,如果前一个盒子的维度依次小于后一个盒子,那么就说明前一个盒子能放入后一个盒子中 这个题目能够转化为最长递增子序列. 首先将盒子的维度从小到大排序,然后将k个盒子,按照排序后的第一维度从小到大排

UVA 10029 Edit Step Ladders ——(DAG求最长路)

题意:升序的给出一本若干个单词,每个单词都可删除一个字母,添加一个字母或者改变一个字母,如果任意一个操作以后能变成另外一个字典中的单词,那么就连一条有向边,求最长的长度. 分析:DAG的最长路和最短路在算法竞赛入门里边原原本本有的,结果我现在忘记了,,真是太弱了..方法就是,用map对应键值(以建图),然后删除操作和修改操作可以看做同一个操作,之后每个操作都是在相应的位置添加一个 '*' 就可以了.想说的有两点,一个是为什么删除和修改可以看做一个操作,其实删除这个操作根本就是多余的,因为一个单词

NYOJ_矩形嵌套(DAG上的最长路 + 经典dp)

本题大意:给定多个矩形的长和宽,让你判断最多能有几个矩形可以嵌套在一起,嵌套的条件为长和宽分别都小于另一个矩形的长和宽. 本题思路:其实这道题和之前做过的一道模版题数字三角形很相似,大体思路都一致,这道题是很经典的DAG上的最长路问题,用dp[ i ]表示以i为出发点的最长路的长度,因为每一步都只能走向他的相邻点,则 d[ i ]  = max(d[ j ] + 1)这里 j 是任意一个面积比 i 小的举行的编号. 下面的代码中附带了最小字典序最长路打印的问题,我们找到第一个路径最长的 i,往后