这一节要讨论的是带有额外条件的DP问题。
以下的这个问题是个很好的例子。
无向图G有N个结点,它的边上带有正的权重值。
你从结点1开始走,并且一开始的时候你身上带有M元钱。如果你经过结点i, 那么你就要花掉S[i]元(可以把这想象为收过路费)。如果你没有足够的钱, 就不能从那个结点经过。在这样的限制条件下,找到从结点1到结点N的最短路径。 或者输出该路径不存在。如果存在多条最短路径,那么输出花钱数量最少的那条。 限制:1
#include
#include
#include
using namespace std;
struct my{
int next,v,w,cost;
};
const int maxn=1000;
const int nil=0x7f7f7f7f;
int tot;
my bian[maxn];
int n,m;
int adj[maxn];
int dp[maxn][maxn],zhi;
bool vis[maxn][maxn];
void myinsert(int u,int v,int w,int cost){
bian[++tot].v=v;
bian[tot].next=adj[u];
adj[u]=tot;
bian[tot].w=w;
bian[tot].cost=cost;
}
void dij(){
for (int i=0;i<=n;i++)
for (int j=0;j<=zhi;j++) dp[i][j]=nil;
dp[1][zhi]=0;
while(true){
int l,k;
int minn=nil;
for (int i=1;i<=n;i++)
for (int j=1;j<=zhi;j++)
if(!vis[i][j]&&dp[i][j]j;
if(minn==nil) break;
vis[l][k]=true;
for (int i=adj[l];i;i=bian[i].next){
int v=bian[i].v;
if(k-bian[i].cost>=0&&dp[v][k-bian[i].cost]>dp[l][k]+bian[i].w){
dp[v][k-bian[i].cost]=dp[l][k]+bian[i].w;
}
}
}
}
int main(){
int u,v,w,cost;
scanf("%d%d%d",&n,&m,&zhi);
for (int i=1;i<=m;i++){
scanf("%d%d%d%d",&u,&v,&w,&cost);
myinsert(u,v,w,cost);
myinsert(v,u,w,cost);
}
dij();
int ans=nil;
for (int j=1;j<=zhi;j++)
if(dp[n][j]<=ans) ans=dp[n][j];
printf("%d\n",ans);
return 0;
}