P2196 [NOIP1996 提高组] 挖地雷 【记搜】

洛谷 P2196 -> Click Here

题意

P1434 滑雪 类似

一个有向图上有N个点,每个点有一个地雷数,询问从任意一点出发,最多能收集多少地雷并打印最优解路径
题面小坑点:边为有向边

思路

记忆化搜索

  • \(A[i]\) :点 \(i\) 的地雷数
  • \(tab[i][j]\) :点 \(i\) 到点 \(j\)​ 是否有路径
  • \(f[i]\) :从点 \(i\)​ 出发最多收集到的地雷数
  • \(vis[i]\) :点 \(i\)​ 是否被访问过
  • \(nxt[i]\) :用来存储路径,打印路径时点 \(i\)​​ 的下一个点

转移方式:\(f[i]=max(f[i],A[i]+f[i所能够到达的点])\)

code

#include<bits/stdc++.h>
using namespace std;
int A[1005],tab[22][22],f[25],vis[25],nxt[25],n;
int go(int x){
	vis[x]=1;
	if(f[x]) return f[x];
	f[x]=A[x];
	for(int i=x+1;i<=n;i++)
		if(tab[x][i]&&vis[i]==0){
			int to=A[x]+go(i);
			if(to>f[x]){
				nxt[x]=i;
				f[x]=to;
			}
		}
	return f[x];
}
void out(int x){
	printf("%d ",x);
	if(!nxt[x]) return;
	out(nxt[x]);
	return;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&A[i]);
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
			scanf("%d",&tab[i][j]);
	int ans=0,sta;
	for(int i=1;i<=n;i++)
		for(int i=1;i<=n;i++) vis[i]=0;
		int to=go(i);
		if(to>ans){
			ans=to;
			sta=i;
		}
	out(sta);
	printf("\n%d\n",ans);
	return 0;
}
posted @ 2021-08-07 10:55  莳曳  阅读(95)  评论(0)    收藏  举报