这是最短路问题和01背包问题的相结合
第一次用01背包
把j打成了i检查了半个小时 下次要注意!
使用的油耗相当于容量 而power相当于价值
先用dijkstra把从基地到所有路的最短情况算出来
然后开始01背包
所有最短路的油耗相加就是总的容量
然后开始dp【j】 算出油耗为j时能获取的最大power
大于总的power的一半时输出
#include <iostream> #include <algorithm> #include <cstring> #include <string> #include<cstdio> using namespace std; #define INF 0x3f3f3f3f #define M 110 int m1[M][M]; int dis[M]; int vis[M]; int n; int v[M]; void dijkstra() { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++)dis[i]=INF; dis[0]=0; vis[0]=1; for(int i=1;i<=n;i++) { int minn=INF; int u=0; for(int j=0;j<=n;j++) { if(!vis[j]&&minn>dis[j]) { u=j;minn=dis[j]; } } vis[u]=1; for(int j=0;j<=n;j++) { if(!vis[j]&&dis[u]+m1[u][j]<dis[j]) dis[j]=dis[u]+m1[u][j]; } } } int main() { int cas;scanf("%d",&cas); while(cas--) { int m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) { if(i==j)m1[i][j]=0; else m1[i][j]=INF; } while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(m1[a][b]>c)m1[a][b]=m1[b][a]=c; } int sumpower=0; for(int i=1;i<=n;i++) { int x;scanf("%d",&x); v[i]=x; sumpower+=x; } sumpower/=2; dijkstra(); int dp[100000]={0}; memset(dp,0,sizeof(dp)); int oil=0; for(int i=1;i<=n;i++) { if(dis[i]!=INF)oil+=dis[i]; } for(int i=1;i<=n;i++) { if(dis[i]!=INF) { for(int j=oil;j>=dis[i];j--) { dp[j]=max(dp[j],dp[ j-dis[i] ]+v[i]); } } } int ok=1;int i; for( i=0;i<=oil;i++) { if(dp[i]>sumpower) { ok=0;break; } } if(ok) printf("impossible "); else printf("%d ",i); } return 0; }
回顾
#include<iostream> #include<queue> #include<cstdio> #include<cstring> #include<vector> using namespace std; #define N 110 #define inf 0x3f3f3f3f int dp[100000]; int n,e,m,s; int vis[N],dis[N],mp[N][N]; int power[N]; void dijkstra(int s) { memset(vis,0,sizeof vis); for(int i=0;i<=n;i++)dis[i]=mp[s][i]; dis[s]=0; for(int i=0;i<=n;i++) { int minn=inf,u=-1; for(int j=1;j<=n;j++) if(dis[j]<minn&&!vis[j]) { minn=dis[j];u=j; } if(u==-1)return ; vis[u]=1; for(int j=1;j<=n;j++) dis[j]=min(dis[j],dis[u]+mp[u][j]); } } int main() { int cas;cin>>cas; while(cas--) { scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) { if(i==j)mp[i][j]=0; else mp[i][j]=inf; } long long oil=0; while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); if(mp[a][b]>c)mp[a][b]=mp[b][a]=c; } int sum=0; for(int i=1;i<=n;i++) { scanf("%d",&power[i]); sum+=power[i]; } dijkstra(0); //背包 价值为能量 容量为耗油 for(int i=1;i<=n;i++) if(dis[i]!=inf)oil+=dis[i]; memset(dp,0,sizeof dp); for(int i=1;i<=n;i++) for(int j=oil;j>=dis[i];j--) dp[j]=max(dp[j],dp[j-dis[i]]+power[i]); sum/=2; int i; for(i=1;i<=oil;i++) if(dp[i]>sum) { printf("%d ",i);break; } if(i==oil+1) printf("impossible "); } return 0; }