【noi 2.6_4978】宠物小精灵之收服(DP)

题意:小智有N个精灵球,皮卡丘有M的初始体力,有K个野生小精灵。要收服尽可能多的野生小精灵,并使皮卡丘的剩余体力最大。

解法:01背包问题,增多一维来存第二个条件。f[i][j][k]表示抓前i个野生小精灵,用了j个精灵球,耗费了k的体力时能抓的最多的小精灵数。(我把[i]的那维简化掉了,PG里的m代替N,v代替M,n代替K。)

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6 #define INF 1e6
 7
 8 int a[110],b[110];
 9 int f[1010][510];
10
11 int main()
12 {
13     int m,v,n;
14     scanf("%d%d%d",&m,&v,&n);
15     for (int i=1;i<=n;i++)
16        scanf("%d%d",&a[i],&b[i]);
17     int mx=0,ans=0;
18     memset(f,0,sizeof(f));
19     for (int i=1;i<=n;i++)
20      for (int j=m;j>=a[i];j--)
21       for (int k=v;k>=b[i];k--)
22       {
23         f[j][k]=max(f[j][k],f[j-a[i]][k-b[i]]+1);
24         if (f[j][k]>mx||(f[j][k]==mx && v-k>ans)) mx=f[j][k],ans=v-k;
25       }
26     if (!mx) ans=v;
27     printf("%d %d\n",mx,ans);
28     return 0;
29 }
时间: 2024-10-19 05:03:55

【noi 2.6_4978】宠物小精灵之收服(DP)的相关文章

(动态规划)4978:宠物小精灵之收服

描述 宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事. 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵.小智也想收服其中的一些小精灵.然而,野生的小精灵并不那么容易被收服.对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力).当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体力小于等于0的野生小精灵也不会被小智收服.当小智的精灵球用完时,狩

宠物小精灵之收服

题目链接 总时间限制: 1000ms 内存限制: 65536kB 描述 宠物小精灵是一部讲述小智和他的搭档皮卡丘一起冒险的故事. 一天,小智和皮卡丘来到了小精灵狩猎场,里面有很多珍贵的野生宠物小精灵.小智也想收服其中的一些小精灵.然而,野生的小精灵并不那么容易被收服.对于每一个野生小精灵而言,小智可能需要使用很多个精灵球才能收服它,而在收服过程中,野生小精灵也会对皮卡丘造成一定的伤害(从而减少皮卡丘的体力).当皮卡丘的体力小于等于0时,小智就必须结束狩猎(因为他需要给皮卡丘疗伤),而使得皮卡丘体

宠物小精灵之收服 (二维01背包)

[题目链接] http://noi.openjudge.cn/ch0206/4978/ [算法] 做的第一道二维的背包问题,只需开的数组增加一维以正确表述每一个状态即可.本质还是多过程决策+最优子结构+无后效性. [代码] 1 #include <bits/stdc++.h> 2 using namespace std; 3 int n,m,k,i,j,t,minm; 4 int v[1010],u[510],dp[1010][510]; 5 int main() 6 { 7 scanf(&q

4978:宠物小精灵之收服

普通01背包再加一维 状态:d[i][j]代表:有i个球,j体力,最多能捕获多少精灵 状态转移:d[i][j]=max(d[i][j],d[i-num[k]][j-val[k]]+1): k为精灵的编号,第k个精灵. 边界情况d[i][0]=d[0][j]=0,都初始化为0也行. 最后找到所剩的体力最大值判断d[N][i]==d[N][M],i是最少消耗的体力值 #include <iostream> #include <cstdio> #include <cstring&g

AcWing 1022. 宠物小精灵之收服

在背包问题中,体积w与价值v是可以互逆的! 可以将\(f[i]\)表示为体积为\(i\)能装的最大价值, 也可以将\(f[i]\)表示为价值为\(i\)所需的最小体积. 两者等价,我们只需要选择范围较小的那维作为体积就可以了! 这直接影响到时空复杂度. 这题就是个案例. 算法1 (体力.精灵球数为费用.精灵数为价值) \(O(nmk)\) \(f[i][j]\)表示为体力为\(i\),精灵球数为\(j\)所收集到的最大精灵. 时间复杂度 差不多是\(5 * 10^7\)的级别. C++ 代码 #

【noi 2.6_3531】判断整除(DP)

题意:给一个正整数数列,可将其相加或相减,问是否有一个结果能被K整除. 解法:似上一题“糖果”的状态定义,f[i][j]表示是否有一个选了前 i 个数的结果模K余j. P.S. 可以用滚动数组. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int N=10010,K=110; 8

【noi 2.6_4982】踩方格(DP)

题意:一个无限大的方格矩阵,能向北.东.西三个方向走.问走N步共有多少种不同的方案. 解法: f[i]表示走 i 格的方案数. 状态转移方程推导如下——设l[i],r[i],u[i]分别为第 i 步向西.东.北的方案数,f[i]为总方案数.l[i]=l[i-1]+u[i-1], r[i]=r[i-1]+u[i-1], u[i]=l[i-1]+r[i-1]+u[i-1]f[i]=l[i]+r[i]+u[i]    =2*l[i-1]+2*r[i-1]+3*u[i-1]    =2*f[i-1]+u

【noi 2.6_6045】开餐馆(DP)

题意:有N个地址,从中选一些开餐馆,要保证相邻餐馆的距离大于k.问最大利润. 解法:f[i]表示在前 i 个地址中选的最大利润. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 7 const int Maxn=110,Maxm=1000010; 8 int m[Maxn],p[Maxn]; 9 i

【noi 2.6_7113】Charm Bracelet(DP)

题意:N个饰物,有重量和渴望程度.问在M的重量限制内能达到的最大的渴望度. 解法:经典的01问题,但有一个小技巧值得记住:用if比较大小比调用max函数快了不少,这题有100ms左右. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define VV 12900 7 int w[VV],d[VV