双调路径

双调路径

题目链接

题目:

给定网格 每条边有两个权值 对于每一权值 越小的路径越优 只有当一条路径两个权值均小于另一路径时 这条路径才比另一条更优 否则两条路径为不同种类的优劣度相同的路径 求最优路径的种数

为什么感觉解释了一下更乱了..

思路:

二维的最短路 这里直接采用 dp
状态:\(f_{i,j}\) 表示当前走到第 \(i\) 号点 花费为 \(j\) 时的最小时间
转移:\(f_{i,j} = min(f_{u,j - cost_v} + time_v)\)
初始化:\(f_{s,j} = 0\) 其余值全部设为极大值
其实直接当背包写就行了
统计答案时 对于 \(f_{e,j}\) 从小到大枚举 \(j\) 记录 \(f_{e,j}\) 当前的最小值 每一次更新最小值的时候累计答案
为什么?
因为我们从小到大枚举的是花费 先枚举到的花费一定比后面的小 这是无论其时间是多少 一定会被选上 至于后面的 则只有当时间更优时会被选上

code:

下面代码中的 g 就是上面的 e

/*
  Time: 1.30
  Worker: Blank_space
  Source: #10083. 「一本通 3.3 例 2」双调路径
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define emm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
struct edge {int v, c, t;};
vector <edge> e[110];
int n, m, s, g, f[110][A], minv = INF, dis[110], ans;
bool vis[110];
queue <int> q;
/*------------------------------------变量定义*/
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
	return x * f;
}
/*----------------------------------------快读*/

/*----------------------------------------函数*/
int main()
{
    n = read(); m = read(); s = read(); g = read();
    for(int i = 1; i <= m; i++)
    {
    	int x = read(), y = read(), z1 = read(), z2 = read();
    	e[x].push_back((edge){y, z1, z2}); e[y].push_back((edge){x, z1, z2});
	}
	emm(f); q.push(s); vis[s] = 1;
	for(int i = 0; i <= 10000; i++) f[s][i] = 0;
	while(!q.empty())
	{
		int u = q.front(); q.pop(); vis[u] = 0;
		for(int i = 0; i < e[u].size(); i++)
		{
			int v = e[u][i].v, c = e[u][i].c, t = e[u][i].t;
			for(int j = 10000; j >= c; j--)
			if(f[v][j] > f[u][j - c] + t)
			{
				f[v][j] = f[u][j - c] + t;
				if(!vis[v]) {vis[v] = 1; q.push(v);}
			}
		}
	}
	for(int i = 0; i <= 10000; i++)
	{
		if(minv > f[g][i])
		{
			ans++;
			minv = f[g][i];
		}
	}
	printf("%d", ans);
	return 0;
}

上一篇:1005:地球人口承载力估计


下一篇:龟龟带你了解在日留学可能会用到的应急电话