#P1893. 第3题-过年
-
1000ms
Tried: 109
Accepted: 17
Difficulty: 5
所属公司 :
京东
时间 :2024年8月17日
-
算法标签>动态规划
第3题-过年
思路:动态规划
定义dp[i][s]表示到点i且花费为s的方案有多少。
那么对于通向点i的点集v∈V,有dp[i][s+wv−>i]+=dp[v][s]
最终答案为dp[n][a]
代码
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int numVertices = scanner.nextInt(), numEdges = scanner.nextInt(), maxWeight = scanner.nextInt();
// 用于存储图中的边
List<int[]> edges = new ArrayList<>();
for(int i = 0 ; i < numEdges ; i ++) {
edges.add(new int[]{scanner.nextInt(), scanner.nextInt(), scanner.nextInt()});
}
// 按照边的权重从小到大排序
edges.sort(Comparator.comparingInt(x -> x[2]));
// 动态规划表,dp[i][j]表示从起点到达第i个顶点且总权重为j的路径数
int[][] dp = new int[numVertices+1][maxWeight+1];
dp[1][0] = 1; // 初始状态,从起点1出发,权重为0的路径数为1
// 用于标记是否存在多余模数的情况
boolean[] overflowFlag = new boolean[numVertices+1];
final int MODULO = 20220201;
for(int weight = 0 ; weight < maxWeight ; weight ++) {
for(int[] edge : edges) {
if(weight + edge[2] > maxWeight) break; // 超过最大权重,跳出循环
dp[edge[1]][weight + edge[2]] += dp[edge[0]][weight];
if(dp[edge[1]][weight + edge[2]] >= MODULO) {
dp[edge[1]][weight + edge[2]] -= MODULO;
overflowFlag[edge[1]] = true; // 标记存在溢出
}
}
}
// 如果存在多余模数的情况,输出特定信息
if(overflowFlag[numVertices]) System.out.println("All roads lead to Home!");
// 输出到达终点n且权重为a的路径数
System.out.println(dp[numVertices][maxWeight]);
}
}
c++
#include<bits/stdc++.h>
using namespace std;
const int N = 105;
struct edge{
int v, w;
};
int main(){
int n, m, a;
cin>>n>>m>>a;
vector<edge>g[N];
for(int i = 0; i < m; i ++){
int u, v, w;
cin>>u>>v>>w;
g[u].push_back({v, w});
}
int dp[N][1005] = {0};
bool st[N][1005];
memset(st, false, sizeof st);
dp[1][0] = 1;//到达节点i,花费为j的方案数
for(int j = 0; j < a; j ++){
for(int i = 1; i <= n; i ++){
for(auto [v, w] : g[i]){
if(j + w <= a){
dp[v][j + w] += dp[i][j];
if(dp[v][j + w] >= 20220201){
dp[v][j + w] %= 20220201;
st[v][j + w] = true;
}
}
}
}
}
if(st[n][a]) cout<<"All roads lead to Home!"<<endl;
cout<<dp[n][a]<<endl;
return 0;
}
java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
* @description:
* @author:CatTail
* @date: 2024/8/19
* @Copyright: https://github.com/CatTailzz
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), m = in.nextInt(), a = in.nextInt();
List<int[]> edges = new ArrayList<>();
for (int i = 0; i < m; i++) {
edges.add(new int[]{in.nextInt(), in.nextInt(), in.nextInt()});
}
// f[i][j] 表示走到i,恰好花费了j的方案数
// 对于i能到达的点集k, 花费c,有f[k][j + c] += f[i][j]
int[][] f = new int[n + 10][a + 10];
f[1][0] = 1;
int MOD = 20220201;
boolean[] isModed = new boolean[n + 10];
for (int w = 0; w <= a; w++) {
for (int[] e : edges) {
if (w + e[2] > a) {
continue;
}
f[e[1]][w + e[2]] += f[e[0]][w];
if (f[e[1]][w + e[2]] >= MOD) {
f[e[1]][w + e[2]] %= MOD;
isModed[e[1]] = true;
}
}
}
if (isModed[n]) {
System.out.println("All roads lead to Home!");
}
System.out.println(f[n][a]);
}
}
题目描述
NN也是要回家过年的呢。
NN所在的国家有 n 座城市,m 条有向道路,第 i 条道路由城市ui通往城市vi,通行费为 wi。
作为一头豪气的N,希望他回家的花费是一个特殊的数字(例如666元)。具体的说,NN希望从城市1移动到城市n,并恰好花费a元。
请你告诉NN,他有多少种回家的方案?
输入描述
第一行三个整数n,m,a(1≤n≤100,1≤m≤1000,1≤a≤1000),含义如题面所示。 接下来m行,第i行三个整数 ui,vi,wi(1≤ui,vi≤n,1≤wi≤a),描述了一条道路。
输出描述
如果NN回家的方家数大于等于 20220201种,请你在第一行输出All roads lead to Home!,然后在第二行输出回家的方案数对 20220201 取模的结里
否则只需要输出一行一个整数,表示NN回家的方案数。
样例
输入
3 6 2
1 2 1
1 2 1
1 2 1
2 3 1
2 3 1
2 3 1
输出
9
说明
从城市一到城市二有3种不同的走法,从城市二到城市三也有3种不同的走法,根据乘法原理我们可以知道,一共有3x3=9种不同的回家方法。