题解:P11595 [NOISG2018 Finals] Journey
主要思路
对于本题,就我而言,第一眼并没有想到动态规划,随即,我打了 dfs。
朴素 dfs
定义函数 dfs(u,val) 表示现在在城市
#include<bits/stdc++.h>
using namespace std;
const int inf=5e8+1;
struct node{
int v,w;
node(){
v=w=0;
}
node(int x,int y){
v=x;
w=y;
}
};
vector<node> e[10010];
//邻接表存图
int ans[410];
int n,m,h;
void dfs(int u,int val){
//搜到目标,计入答案,跳出递归
if(u==n-1){
if(ans[val]==inf) return;
ans[val]++;
return ;
}
for(auto t:e[u]){
//沿边搜索
int v=t.v;
int w=val+t.w;
if(w>m){
continue;
}
for(int i=w;i<=m;i++){
dfs(v,i);
}
}
}
int main(){
//关同步流
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>h;
for(int i=0;i<n-1;i++){
for(int j=1;j<=h;j++){
int v,w;
cin>>v>>w;
e[i].push_back(node(v,w));
//建边
}
}
dfs(0,1);
for(int i=1;i<=m;i++){
cout<<ans[i]<<' ';
}
return 0;
}
记忆化搜索
定义函数 dfs(u,val) 表示现在在城市
#include<bits/stdc++.h>
using namespace std;
const int inf=5e8+1;
struct node{
int v,w;
node(){
v=w=0;
}
node(int x,int y){
v=x;
w=y;
}
};
vector<node> e[10010];
int n,m,h;
int f[10010][410];
int dfs(int u,int val){
int sum=0;
if(f[u][val]!=0){
return f[u][val];
}
if(u==0&&val==1){
return 1;
}
for(auto t:e[u]){
int v=t.v;
int w=val-t.w;
for(int i=w;i>=1;i--){
sum+=dfs(v,i);
}
}
return sum;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>h;
for(int i=0;i<n-1;i++){
for(int j=1;j<=h;j++){
int v,w;
cin>>v>>w;
if(v>i)
e[v].push_back(node(i,w));
}
}
for(int i=1;i<=m;i++){
cout<<dfs(n-1,i)<<' ';
}
return 0;
}
动态规划
由记忆化搜索更改为递推形式,得出动态规划 AC 代码。
#include<bits/stdc++.h>
using namespace std;
const int inf=5e8+1;
struct node{
int v,w;
node(){
v=w=0;
}
node(int x,int y){
v=x;
w=y;
}
};
vector<node> e[10010];
int n,m,h;
int f[10010][410];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>h;
f[0][1]=1;
for(int i=0;i<n-1;i++){
for(int j=1;j<=h;j++){
int v,w;
cin>>v>>w;
if(v>i)
e[i].push_back(node(v,w));
}
}
for(int i=0;i<n-1;i++){
if(i!=0)
for(int j=1;j<=m;j++){
f[i][j]+=f[i][j-1];
if(f[i][j]>inf) f[i][j]=inf;
}
for(auto t:e[i]){
int v=t.v;
int w=t.w;
for(int j=w;j<=m;j++){
f[v][j]+=f[i][j-w];
if(f[v][j]>inf) f[v][j]=inf;
}
}
}
for(int j=1;j<=m;j++){
f[n-1][j]+=f[n-1][j-1];
if(f[n-1][j]>inf) f[n-1][j]=inf;
}
for(int i=1;i<=m;i++){
cout<<f[n-1][i]<<' ';
}
return 0;
}