萌新6:16进制世界(dp)

2024-09-04 05:52
文章标签 16 dp 世界 进制 萌新

本文主要是介绍萌新6:16进制世界(dp),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


 

题目描述

这是一个16进制的世界,比如522的16进制是20A。

在5月22日那天,有人送给Bob一些月饼,每个月饼有饱食度和幸福度两个属性。

现在Bob有nnn个月饼,对于每个月饼iii,饱食度为viv_ivi​,幸福度为wiw_iwi​。

Bob现在有mmm饱食度,意味着他吃的月饼的饱食度之和不大于mmm。

但是由于Bob身处16进制的世界,他吃的月饼的幸福度之和必须是16的倍数。

请帮Bob算一下他最多吃的月饼的数量。

输入描述:

第一行输入两个整数n, mn,\ mn, m接下来nnn行分别输入vi, wiv_i, \ w_ivi​, wi​表示第iii个月饼的饱食度和幸福度。输入数据保证1≤n⋅m≤1051 \leq n \cdot m \leq 10^51≤n⋅m≤105, 1≤vi≤1051 \leq v_i \leq 10^51≤vi​≤105, 1≤wi≤1091 \leq w_i \leq 10^91≤wi​≤109。

输出描述:

一个整数,表示Bob最多能吃的月饼数量

示例1

输入

复制2 5 2 16 3 15

2 5
2 16
3 15

输出

复制1

1

做法

dp[i][j][k]为考虑了前i个月饼,当前的饱食度为j,幸福值为k时选取的月饼个数,这是最先想到的。但是呢,这样会爆空间。我们又看到,要求幸福值为16的倍数,那么我们就去余数就好了,k的那一位不用开那么大。

dp数组递推:从当前位置往前推

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
struct ty{int v,w;  
}a[100010];
signed main(){scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++){scanf("%lld%lld",&a[i].v,&a[i].w);}vector<vector< vector<int> > > dp(n+1,vector< vector<int> >(m+1,vector<int>(16)));//考虑了前i个月饼,当前的饱食度为j,幸福值为k(16以内,取模)的个数for(int i=0;i<=n;i++){//初始化!!!!for(int j=0;j<=m;j++){for(int k=0;k<16;k++){dp[i][j][k]=-0x3f3f3f3f;}}}dp[0][0][0]=0;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){for(int k=0;k<16;k++){//不选dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]);//选if(a[i].v<=j){//从当前位置往前推if(a[i].w%16<=k) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a[i].v][k-a[i].w%16]+1);else if(16+k-a[i].w%16<16) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a[i].v][16+k-a[i].w%16]+1);}} }}int ans=0;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){ans=max(dp[i][j][0],ans);}}cout<<ans;}

dp数组递推:从当前位置往后推

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
struct ty{int v,w;  
}a[100010];
signed main(){scanf("%lld%lld",&n,&m);for(int i=1;i<=n;i++){scanf("%lld%lld",&a[i].v,&a[i].w);}vector<vector< vector<int> > > dp(n+1,vector< vector<int> >(m+1,vector<int>(16)));//考虑了前i个月饼,当前的饱食度为j,幸福值为k(16以内,取模)的个数for(int i=0;i<=n;i++){for(int j=0;j<=m;j++){for(int k=0;k<16;k++){dp[i][j][k]=-0x3f3f3f3f;}}}dp[0][0][0]=0;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){for(int k=0;k<16;k++){dp[i][j][k]=max(dp[i-1][j][k],dp[i][j][k]);//一定要赋值!!!if(j+a[i].v<=m){//从当前位置往后推//不选dp[i][j+a[i].v][(k+a[i].w%16)%16]=max(dp[i-1][j+a[i].v][(k+a[i].w%16)%16],dp[i][j+a[i].v][(k+a[i].w%16)%16]);//选dp[i][j+a[i].v][(k+a[i].w%16)%16]=max(dp[i-1][j][k]+1,dp[i][j+a[i].v][(k+a[i].w%16)%16]);}} }}int ans=0;for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){ans=max(dp[i][j][0],ans);}}cout<<ans;}

WA的原因

1.dp数组没有初始化为负数。之前写的一些dp题,求最大值都不用初始化dp数组,因为本身就为0,所以就理所当然了。

2.每层都要赋好值(第二种方法)。要考虑到选和不选的情况,特别是不选的情况。

这篇关于萌新6:16进制世界(dp)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1135176

相关文章

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

hdu4865(概率DP)

题意:已知前一天和今天的天气概率,某天的天气概率和叶子的潮湿程度的概率,n天叶子的湿度,求n天最有可能的天气情况。 思路:概率DP,dp[i][j]表示第i天天气为j的概率,状态转移如下:dp[i][j] = max(dp[i][j, dp[i-1][k]*table2[k][j]*table1[j][col] )  代码如下: #include <stdio.h>#include

usaco 1.2 Palindromic Squares(进制转化)

考察进制转化 注意一些细节就可以了 直接上代码: /*ID: who jayLANG: C++TASK: palsquare*/#include<stdio.h>int x[20],xlen,y[20],ylen,B;void change(int n){int m;m=n;xlen=0;while(m){x[++xlen]=m%B;m/=B;}m=n*n;ylen=0;whi

usaco 1.1 Broken Necklace(DP)

直接上代码 接触的第一道dp ps.大概的思路就是 先从左往右用一个数组在每个点记下蓝或黑的个数 再从右到左算一遍 最后取出最大的即可 核心语句在于: 如果 str[i] = 'r'  ,   rl[i]=rl[i-1]+1, bl[i]=0 如果 str[i] = 'b' ,  bl[i]=bl[i-1]+1, rl[i]=0 如果 str[i] = 'w',  bl[i]=b

uva 10061 How many zero's and how many digits ?(不同进制阶乘末尾几个0)+poj 1401

题意是求在base进制下的 n!的结果有几位数,末尾有几个0。 想起刚开始的时候做的一道10进制下的n阶乘末尾有几个零,以及之前有做过的一道n阶乘的位数。 当时都是在10进制下的。 10进制下的做法是: 1. n阶位数:直接 lg(n!)就是得数的位数。 2. n阶末尾0的个数:由于2 * 5 将会在得数中以0的形式存在,所以计算2或者计算5,由于因子中出现5必然出现2,所以直接一

uva 10154 DP 叠乌龟

题意: 给你几只乌龟,每只乌龟有自身的重量和力量。 每只乌龟的力量可以承受自身体重和在其上的几只乌龟的体重和内。 问最多能叠放几只乌龟。 解析: 先将乌龟按力量从小到大排列。 然后dp的时候从前往后叠,状态转移方程: dp[i][j] = dp[i - 1][j];if (dp[i - 1][j - 1] != inf && dp[i - 1][j - 1] <= t[i]

uva 10118 dP

题意: 给4列篮子,每次从某一列开始无放回拿蜡烛放入篮子里,并且篮子最多只能放5支蜡烛,数字代表蜡烛的颜色。 当拿出当前颜色的蜡烛在篮子里存在时,猪脚可以把蜡烛带回家。 问最多拿多少只蜡烛。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cs

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl