http://acm.timus.ru/problem.aspx?space=1&num=1570
此题如果只求最少花费的话,就可以简单的dp或是背包就可以了
难就难在在选择路径上有困难 应该在记录路径时 记下所有可能是最优的路径 排除一定不是最优的路径
然后选择一条最优的总路径
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<set> #include<map> #include<string> #include<queue> #include<stack> #include <iomanip> using namespace std; #define LL long long const double eps=1e-6; const int INF=0x3f3f3f3f; const int N=40005; const int M=105; struct node { string name; int cost; int weight; }mem[M]; int dp[N],num[N],f[N]; vector<int>vtf[N],vtnum[N]; int sum[M]; int n,m; bool cmp(node x,node y) { return x.cost<y.cost; } void packComplete(int k,int cost,int weight,int V) { for(int v=cost;v<=V;++v) { if(v-cost>=m) break; if(dp[v-cost]+weight>dp[v]) continue; if(dp[v-cost]+weight<dp[v]) { vtf[v].clear();vtnum[v].clear(); dp[v]=dp[v-cost]+weight; num[v]=num[v-cost]+((f[v-cost]==k)?0:1); vtf[v].push_back(k);vtnum[v].push_back(num[v]); f[v]=k; }else if(num[v-cost]+((f[v-cost]==k)?0:1)>num[v]) { num[v]=num[v-cost]+((f[v-cost]==k)?0:1); vtf[v].push_back(k);vtnum[v].push_back(num[v]); f[v]=k; } } } int main() { //freopen("data.in","r",stdin); while(cin>>n>>m) { m=int(m*1000+eps); int V=N-5; for(int i=1;i<=n;++i) { double ftmp; cin>>mem[i].name>>mem[i].weight>>ftmp; mem[i].cost=int(ftmp*1000+eps); } sort(mem+1,mem+n+1,cmp); memset(f,0,sizeof(f)); memset(num,0,sizeof(num)); for(int i=1;i<=V;++i) dp[i]=INF; dp[0]=0; for(int i=1;i<=n;++i) packComplete(i,mem[i].cost,mem[i].weight,V); memset(sum,0,sizeof(sum)); int k=V; for(int i=m;i<V;++i) if(dp[i]<dp[k]||(dp[i]==dp[k]&&num[i]>num[k])) k=i; cout<<dp[k]<<endl; int pnum=num[k],pk=-1; while(k!=0) { for(unsigned int i=0;i<vtf[k].size();++i) { if(vtnum[k][i]+((vtf[k][i]==pk||pk==-1)?0:1)==pnum) { pnum=vtnum[k][i]; pk=vtf[k][i]; ++sum[pk]; k=k-mem[pk].cost; break; } } } for(int i=1;i<=n;++i) if(sum[i]!=0) cout<<mem[i].name<<" "<<sum[i]<<endl; } return 0; }