1570.Eating High
3111 ワード
http://acm.timus.ru/problem.aspx?space=1&num=1570
この問題は少なくともお金が必要なら、簡単なdpやバックパックで大丈夫です.
選択経路に困難があるのは難しいです. パスを記録する時に、最適かもしれないすべてのパスを記録してください.最適なパス除外は必ずしも最適なパスではありません.
その後、最適なパスを選択します.
コード:
この問題は少なくともお金が必要なら、簡単な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;
}