声明:此解法纯属恶搞,标答请点这里
不知道最短路的请点 这里
让我们开始这次最短路算法的讲解(不会让你短路)
题目 来啦
yxc曾留下一句至理名言:
DP与最短路是相通的。
能不能把背包问题与最短路转化呢?
我点开了这道题目。
最短路……该怎么转化呢?
先看看DP怎么做吧。
#include <iostream>
#include <algorithm>
using namespace std ;
const int N=1010 ;
int f[N] ;
int v,w ;
int n,m ;
int main()
{
scanf("%d%d",&n,&m) ;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v,&w) ;
for(int j=v;j<=m;j++)
f[j]=max(f[j],f[j-v]+w) ;
}
printf("%d",f[m]) ;
return 0 ;
}
我们可以模仿dp中的f
数组,让dis[i]
表示体积从0到i的“距离”。
距离的定义是什么?i到j的距离就是背包内物品总体积为i的最大价值与总体积为j的最大价值的差
这样,dis[m]
就是总体积为m的最大价值
DP成功转型!
注意事项
问题求的是最大价值,所以应该求“最长路”才对。
这里最短路是从0号点开始的,不是一号点。
另外,每个j-v
与j
之间应连一条权值为 w
的边,这样问题就得以解决。
本人用的是SPFA求最短路
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std ;
const int N=1010,M=N*1000 ;
int dis[N] ;
int h[N],e[M],ne[M],w[M],idx ;
bool st[N] ;
int v,worth ;
int n,m ;
void add(int a,int b,int c)
{
e[idx]=b ;
w[idx]=c ;
ne[idx]=h[a] ;
h[a]=idx++ ;
}
void spfa()
{
queue<int> q ;
q.push(0) ;
dis[0]=0 ;
st[0]=true ;
while(q.size())
{
int t=q.front() ;
q.pop() ;
st[t]=false ;
for(int i=h[t];~i;i=ne[i])
{
int j=e[i] ;
if(dis[j]<dis[t]+w[i])
{
dis[j]=dis[t]+w[i] ;
if(!st[j])
{
st[j]=true ;
q.push(j) ;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&m) ;
memset(h,-1,sizeof h) ;
memset(dis,-1,sizeof dis) ;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&v,&worth) ;
for(int j=0;j<=m-v;j++)
add(j,j+v,worth) ;
}
spfa() ;
printf("%d",dis[m]) ;
return 0 ;
}
很精彩!请问一下01背包可以转化成最短路问题吗,我思考了很久也想不出来…
我也想了下,只是01背包只能选一次,最后转化的结果就是有不同种类的路径,每类路径只能走一次,我是不会做