zoukankan      html  css  js  c++  java
  • 4.20 DP-挖地雷 题解

    题意

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

    题解

    注意到原图是一个有向无环图,则想到拓扑排序。
    不难发现,对于(u o v),有(dp[v]=max(dp[v],dp[u]+a[v])).
    注意初始化:(dp[1cdots n]=a[1cdots n])

    注意

    开始的时候没有想到“正解是只在一个点内走”的情况,此时拓扑排序不可用,需要预处理一下!
    导致80分WA卡了近二十分钟!

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin),freope(a".out","w",stdout)
    using namespace std;
    const int INF = 0x3f3f3f3f , N = 2e2+5, M = 4e4+5;
    typedef unsigned long long ull;
    typedef long long ll;
    inline ll read(){
    	int ret = 0 ;
    	char ch = ' ' , c = getchar();
    	while(!(c >= '0' && c <= '9')) ch = c , c = getchar();
    	while(c >= '0' && c <= '9')ret = (ret << 1) + (ret << 3) + c - '0' , c = getchar();
    	return ch == '-' ? -ret : ret;
    }
    struct Edge{
    	int to,nxt;
    }e[M];
    int ecnt = -1,head[N],ind[N];
    inline void add_edge(int u,int v){
    	ind[v]++;
    	e[++ecnt] = (Edge){v,head[u]};
    	head[u] = ecnt;
    }
    int n;
    int a[N],x,y;
    int maxn = -INF,pos,dp[N],pre[N];
    void print(int x){
    	if(!x)return;
    	print(pre[x]);
    	printf("%d-",x);
    }
    queue<int>q;
    inline void topo(){
    	for(int i = 1 ; i <= n ; i ++)
    		if(!ind[i])
    			q.push(i);
    	while(!q.empty()){
    		int u = q.front(); q.pop();
    		for(int i = head[u] ; ~i ; i = e[i].nxt){
    			int v = e[i].to;
    			if(dp[v] < dp[u] + a[v]){
    				dp[v] = dp[u] + a[v];
    				pre[v] = u;
    				if(dp[v] > maxn)
    					maxn = dp[v] ,
    					pos = v ;
    			}
    			if(!--ind[v])
    				q.push(v);
    		}
    	}
    }
    inline void init(){memset(head,-1,sizeof(head));}
    signed main(){
    	init();
    	n = read();
    	for(int i = 1 ; i <= n ; i ++){
    		dp[i] = a[i] = read();
    		if(dp[i] > maxn)
    			maxn = dp[i],pos = i;
    	}
    	while(1){
    		x = read() , y = read();
    		if(!x && !y)break;
    		add_edge(x,y);
    	}
    	topo();
    	print(pre[pos]);
    	printf("%d
    ",pos);
    	
    	printf("%d",maxn);
    	return 0;
    }
    
  • 相关阅读:
    Python(条件判断和循环)
    大端还是小端
    c语言程序设计 字符串拷贝拷贝演变与初衷
    内存 匹配串
    多态 C2
    多态 C1
    判断是否存在不合法字符(C++)
    va_start、vsprintf、va_end
    java中instanceof用法
    c++ vector相关
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/14682701.html
Copyright © 2011-2022 走看看