G.房间迷宫(优化dj最短路)

房间迷宫

题目链接https://www.cometoj.com/contest/33/problem/G
验证码:jwjtxdy

题目描述

鸡尾酒被困入了一个迷宫!

这个迷宫总共有n个房间组成,鸡尾酒初始在1号房间,n号房间为迷宫的出口。每进入一次第i个房间都需要缴纳ai的过路费(包括初始的一号房间)。每个房间有一张纸条和一个箱子。纸条上写着的数字di代表鸡尾酒下一个可以到达的房间编号。

鸡尾酒也可以选择花费bi的金钱打开箱子,箱子中有一个密码ci,打开箱子之后鸡尾酒可以移动到i+k号房间,其中c可被k整除。但如果i+k>n,则不能移动。

求鸡尾酒从走出迷宫的最小花费。若鸡尾酒无法走出迷宫,输出-1。

输入描述

输入第一行一个n,代表迷宫共有n个房间(n<2e5)

接下来有n行,每行包含四个整数ai,bi,ci,di,意义如题面所描述。其中(ai,bi,ci,di≤2e5)

输出描述

输出一行一个整数代表走出迷宫的最小花费。

样例输入 1

5
1 2 2 4
2 2 2 2
1 1 2 2
100 1 1 1
1 1 1 1

样例输出 1

6


这题显然是个最短路,我们只要注意存边的时候将c的因子囊括进来就好了,我们可以先筛选每个数的因子,利用埃氏筛同时加vector存因子:

for(int i=1; i<mac; ++i) {
	for(int j = i; j<mac; j+=i) {
		yinzi[j].push_back(i);
	}
}

存边的时候还要注意i-i的距离为0,接下来就是没有什么好说的了,就是一个优先队列+vector优化的迪杰斯特拉最短路:

#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#define ll long long
#define inf 999999999999
#define mac 200050
using namespace std;
struct node {
	int to, cost;
};
struct node2 {
	int id;
	ll d;
	bool friend operator < (node2 n1, node2 n2) {
		return n1.d > n2.d;
	}
};
vector<node>g[mac];
vector<int>yinzi[mac];
ll dis[mac];
int vis[mac];
int a[mac],b[mac],c[mac],d[mac];
void dj(int s);
int main()
{
	int n;
	for(int i=1;i<mac;++i) {
        for(int j = i;j<mac;j+=i) {
            yinzi[j].push_back(i);
        }
    }
	scanf ("%d",&n);
	for (int i=1; i<=n; i++){
		scanf ("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
	}
	for (int i=1; i<=n; i++){
		node n1,n2;
		if (d[i]!=i){
			n1.to=d[i];
		    n1.cost=a[d[i]];
		    g[i].push_back(n1);
		}	
		for (int j=0; j<yinzi[c[i]].size(); j++){
			int pp=yinzi[c[i]][j];
			if (pp+i>n) break;
			n1.to=i+pp;
			n1.cost=a[i+pp]+b[i];
			g[i].push_back(n1);
		}	
	}
	for (int i=1; i<=n; i++) dis[i]=inf;
	dj(1);
	if (dis[n]==inf) printf ("-1\n");
	else printf ("%lld\n",dis[n]+a[1]);
	return 0;
}
void dj(int s)
{
	priority_queue<node2>q;
	dis[s]=0;
	node2 k;
	k.id=s;
	k.d=0;
	q.push(k);
	while (!q.empty()){
		node2 ks=q.top();q.pop();
		int now=ks.id;
		if (vis[now]) continue;
		vis[now]=1;
		for (int i=0; i<g[now].size(); i++){
			if (!vis[g[now][i].to] && (ll)g[now][i].cost+dis[now]<dis[g[now][i].to]){
				dis[g[now][i].to]=(ll)g[now][i].cost+dis[now];
				node2 kis;
				kis.d=dis[g[now][i].to],kis.id=g[now][i].to;
				q.push(kis);
			}
		}	
	}
}

猜你喜欢

转载自blog.csdn.net/qq_43906000/article/details/89045931