Mars Stomatology Gym

来源:互联网 发布:在手机淘宝怎么删评价 编辑:程序博客网 时间:2024/06/04 18:44

题目链接

题意: 给出n,k,p 代表 坏牙数 棉花数 钱数  给出 棉花价格  给出 补牙价格 补牙所在牙龈 一个棉花可以用于一个牙龈 i代表牙龈,j代表总补牙数,z代表这层的补牙数 

   思路:

dp[i][j]表示前i个牙龈共修j颗牙的花费, 为了求的最大的修牙数我们队每个牙龈上的牙的价钱按照升序排序 优先修最便宜的,记录一下每个牙龈上修牙价钱的前缀和,然后枚举第i个牙龈上修几颗牙,然后对于同样的修牙数去价钱的最小值

对于修的哪几颗牙,我们可以换个角度来想,我们只需记录每个牙龈上修了几颗牙即可.然后顺序输出.

#include<bits/stdc++.h>#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 100000007#define inf 0x3f3f3f3fusing namespace std;typedef long long ll;const int maxn=1e5+10;int dp[666][666],sum[666][666],num[666][666];int a[666];vector<pair<int,int> >vt[666]; int n,k,p;void solve(){CLR(sum,0);for(int i=1;i<=n;i++)sort(vt[i].begin(),vt[i].end());for(int i=1;i<=k;i++){for(int j=0;j<vt[i].size();j++){sum[i][j+1]=sum[i][j]+vt[i][j].first;}}CLR(dp,inf);CLR(num,0);dp[0][0]=0;for(int i=1;i<=k;i++){for(int j=0;j<=n;j++){for(int k=0;k<=vt[i].size();k++){if(k>j)break;if(k==0){num[i][j]=0;  dp[i][j]=min(dp[i][j],dp[i-1][j]);}else{if(dp[i][j]>dp[i-1][j-k]+sum[i][k]+a[i]){num[i][j]=k;dp[i][j]=dp[i-1][j-k]+sum[i][k]+a[i];}}}}}int cnt,item=n;for(int i=1;i<=n;i++){if(dp[k][i]>p){cnt=i-1;break;}}Pi(cnt);while(cnt){for(int i=0;i<num[item][cnt];i++)printf("%d ",vt[item][i].second);cnt-=num[item][cnt];item--;}}int main(){Ri(n),Ri(k),Ri(p);for(int i=1;i<=k;i++)Ri(a[i]);int b,c;for(int i=1;i<=n;i++){Ri(b),Ri(c);vt[c].push_back(make_pair(b,i));}solve();return 0; }

0 0
原创粉丝点击