双调路径
双调路径
题目链接
题目:
给定网格 每条边有两个权值 对于每一权值 越小的路径越优 只有当一条路径两个权值均小于另一路径时 这条路径才比另一条更优 否则两条路径为不同种类的优劣度相同的路径 求最优路径的种数
为什么感觉解释了一下更乱了..
思路:
二维的最短路 这里直接采用 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;
}