Mars Stomatology gym 1007651 补牙(dp)

来源:互联网 发布:java wait notify使用 编辑:程序博客网 时间:2024/05/16 02:05

Problem I. Mars Stomatology
Martian girl Kate has a toothache. The martian anatomy is very
specific. They all have N teeth, each situated on one of K gums.
Kate should pay dentist Ai mars euros for the treatment of i-th
tooth. Moreover, Kate should pay Bj euros for the anesthesia of the
gum j if this gum has at least one tooth cured. What is the maximal
number of teeth Kate can cure if parents gave her P mars euros?
Input
The first line of the input contains three integer numbers N, K and
P (1 ≤ N ≤ 600; 1 ≤ K ≤ N; 1 ≤ P ≤ 106
). The second line
contains the sequence of K integer numbers B1, B2, … , BK, where
Bj is the cost of anesthesia of the j-th gum (1 ≤ Bj ≤ 600 for
all j = 1,2, … , K). Each of the following N lines contains the
description of tooth. Each description is the pair of integer numbers
Ai and Ci, where Ai is the cost of curing of the i-th tooth, Ci is the
number of the gum the tooth occupies (1 ≤ Ai ≤ 600; 1 ≤ Ci ≤ K
for all i = 1,2, … , N).
Output
Write to the first line of the output the maximal number of cured
teeth S. Write to the second line S numbers of the cured teeth from
the given set. If there are several solutions output any of them.

题意 给出n,k,p 代表 坏牙数 棉花数 钱数
给出 棉花价格
给出 补牙价格 补牙所在牙龈
一个棉花可以用于一个牙龈
i代表牙龈,j代表总补牙数,z代表这层的补牙数
状态转移方程 dp[i][j]=min(dp[i][j],dp[i-1][j-z]+sum[i][z]+a[i]*(z!=0));
还要记录路径,怎么记录路径呢。
记录每层缩小的时间补牙的个数就好
最后找到第一个大于p的状态 就可以逆推输出结果了

#include <bits/stdc++.h>using namespace std;int dp[700][700],pre[700][700],sum[700][700];vector<pair<int,int> > v[700];int a[700];const int inf=0x3f3f3f3f;int main(){    int n,k,p;    scanf("%d%d%d",&n,&k,&p);    for(int i=1;i<=k;i++)        scanf("%d",&a[i]);    for(int i=1;i<=n;i++)    {        int c,d;        scanf("%d%d",&c,&d);        v[d].push_back(make_pair(c,i));    }    for(int i=1;i<=k;i++)        sort(v[i].begin(),v[i].end());    for(int i=1;i<=k;i++)    {        for(int j=0;j<v[i].size();j++)            sum[i][j+1]=sum[i][j]+v[i][j].first;    }    memset(dp,inf,sizeof(dp));    dp[0][0]=0;    for(int i=1;i<=k;i++)    {        for(int j=0;j<=n;j++)        {            for(int z=0;z<=v[i].size();z++)            {                if(z>j) continue;                if(dp[i][j]>dp[i-1][j-z]+sum[i][z]+a[i]*(z!=0))                {                    pre[i][j]=z;                    dp[i][j]=min(dp[i][j],dp[i-1][j-z]+sum[i][z]+a[i]*(z!=0));                }            }        }    }    for(int i=1;i<=n+1;i++)    {        if(dp[k][i]>p){            printf("%d\n",i-1 );            int num=i-1;            int now=k;            while(num)            {                for(int j=0;j<pre[now][num];j++)                    printf("%d ",v[now][j].second );             num-=pre[now][num];            now--;            }            return 0;        }    }    return 0;}
1 0
原创粉丝点击