水dp第二天(背包有关)
水dp第二天(背包有关)
标签: dp
- 题意:裸的01背包
- 注意:这种题要注意两个问题,一个是要看清楚数组要开的范围大小,然后考虑需要空间优化吗,还有事用int还是long long
- 代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 13000;
int W[N],D[N];
int dp[N];
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
memset(dp,0,sizeof(dp));
for(int i = 0; i < n; i++){
scanf("%d%d",&D[i],&W[i]);
}
for(int i = 0; i < n; i++){
for(int j = m; j >= D[i]; j--){
dp[j] = max(dp[j],dp[j-D[i]]+W[i]);
}
}
printf("%d\n",dp[m]);
}
return 0;
}
- 题意:最长上升子序列
- 注意:如果不要求输出上升序列的话就可以采用O(nlogn)的算法
- 算法讲解:维护一个数组,每次考虑一个新加入的元素时,如果这个元素比数组最后一个大的话,那么直接把这个元素放在数组的后面,否则的话,通过二分查找找到这个数组中第一个比当前值大的元素,替换这个元素,因为新加入的元素比这个元素更具有“潜力”。
- 算法注意:二分的时候一定要仔细是L<=R因为这个wa了好多次。还要注意因为是每次都要判断是否可以吧这个元素加入数组,所以考虑0的情况则不能把数组初始化为0,而应初始化为-1,并且数组应该是从1开始标号,保证第一个数可以通过判断加入数组中。(考虑一下,通过这样方式得到的数组一定是一个有序的数组,而且一定是一个增序的数组),如果要想得到不减的数组,在和最后一个元素比较的时候相等也加入队列即可。
- 代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int stk[N];
int cnt;
int BSearch(int l,int r, int c)
{
while(l<=r){//注意这里应该是定于的时候还要再判断一次。
int m = (l+r)>>1;
if(stk[m]==c) {
//printf("id = %d\n",m);
return m;
}
else if(stk[m]<c) l = m+1;
else if(stk[m]>c) r = m-1;
}
//printf("id = %d\n",l);
return l;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==0) {puts("1"); continue;}
int cnt = 1;//因为cnt = 0的时候第一个数字没办法判断入栈情况
memset(stk,-1,sizeof(stk));
int tm;
for(int i = 0; i < n; i++){
scanf("%d",&tm);
if(tm>stk[cnt-1]){
stk[cnt++] = tm;
}
else {
int id = BSearch(1,cnt-1,tm);
stk[id] = tm;
}
}
printf("%d\n",cnt-1);
}
return 0;
}
- 题意:中文题意说的很清楚了
- 题解:这个题有意思,因为是如果最后还剩下5块钱的时候就可以买任意多的东西,所以考虑用最后的5块钱去买最贵的一种,然后剩下的n-1中物品就要尽可能多的花到总钱数-5,就是一个典型的01背包问题了。那么问题自然来了,考虑两种特殊情况,如果一开始钱就小于5,或者是给的钱-5就可以吧所有的东西都买完了,这两种情况很简单,特判一下就可以了
- 代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2000;
int cost[N];
int dp[N];//dp[i][j]表示考虑到第i个菜余额是j的时候的最大花费
int main()
{
int n,m,sum;
while(~scanf("%d",&n),n)
{
sum = 0;
for(int i = 0; i < n; i++){
scanf("%d",&cost[i]);
sum+=cost[i];
}
sort(cost, cost+n);
scanf("%d",&m);
if(m<5){
printf("%d\n",m);
continue;
}
if(m>sum){
printf("%d\n",m-sum);
continue;
}
m = m-5;
memset(dp,0,sizeof(dp));
for(int i = 0; i < n-1; i++){
for(int j = m; j>=cost[i]; j--){
dp[j] = max(dp[j],dp[j-cost[i]]+cost[i]);
}
}
printf("%d\n",m+5-dp[m]-cost[n-1]);
}
return 0;
}
- 题意:要猜一个存钱罐里最少有多少钱。而且如果不存在一种可能装到当前重量的话,要输出不可能
- 题解:这是很简单的完全背包恰好被装满的情况,这种问题和一般的背包比较就是初始化不同,要把所有不符合条件的状态标记成-1,然后符合条件的状态可以进行转移。
- 注意:要精确的吧dp写对,就一定要把每个状态是从哪个状态转移来的,每个状态一旦确定会不会受到后面状态的影响想清楚,仔细画一个图也可以很清楚的找到这个空间优化的方法了
- 代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 550;
int p[N],w[N];
int dp[N*500];
int main()
{
int T,n,l,r,val;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&l,&r);
val = r-l;
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%d%d",&p[i],&w[i]);
}
memset(dp,-1,sizeof(dp));
dp[0] = 0;
for(int i = 0; i < n; i++){
for(int j = w[i]; j <= val; j++){
if(dp[j]==-1&&dp[j-w[i]]==-1) continue;
else if(dp[j]==-1) dp[j] = dp[j-w[i]]+p[i];
else if(dp[j-w[i]] == -1) dp[j] = dp[j];
else dp[j] = min(dp[j],dp[j-w[i]]+p[i]);
}
}
if(dp[val]==-1) puts("This is impossible.");
else printf("The minimum amount of money in the piggy-bank is %d.\n",dp[val]);
}
return 0;
}
- 题意:这个题是一个裸的多重背包。可以直接套用模板,经过我被上一个模板坑了1个小时的精力,终于把之前的模板调通了
- 代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 110
int val;
int f[N*500];
//每件物品只能使用一次
void onezeropack(int v,int c)
{
int j;
for(j=val; j>=v; j--)
{
f[j]=max(f[j-v]+c,f[j]);
}
}
//每件物品可以无限使用
void completepack(int v,int c)
{
int j;
for(j=v; j<=val; j++)
{
f[j]=max(f[j-v]+c,f[j]);
}
}
//每件物品有限次使用
void multiplepack(int v,int c,int num)
{
if(v*num>=val)
{
completepack(v,c);
return;
}
int k=1;
while(k<num)
{
onezeropack(k*v,k*c);
num=num-k;
// printf(" - num = %d\n", num);
k=k*2;
}
//printf("num = %d\n", num);
onezeropack(num*v,num*c);
}
int v[N], num[N], w[N];
int main()
{
int T,n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
val = n;
for(int i = 0; i < m; i++){
scanf("%d%d%d",&v[i],&w[i],&num[i]);
}
memset(f,0,sizeof(f));
for(int i = 0; i < m; i++){
multiplepack(v[i],w[i],num[i]);
}
printf("%d\n",f[val]);
}
return 0;
}
- 又是一道背包水题
- 代码:
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAX=100000;
int dp[MAX];
int c[MAX],w[MAX];
int v;
void ZeroOnePack(int cost,int wei)//01
{
int i;
for(i = v;i>=cost;i--)
{
dp[i] = max(dp[i],dp[i-cost]+wei);
}
}
void CompletePack(int cost,int wei)//完全
{
int i;
for(i = cost;i<=v;i++)
{
dp[i] = max(dp[i],dp[i-cost]+wei);
}
}
void MultiplePack(int cost,int wei,int cnt)//多重
{
if(v<=cnt*cost)//如果总容量比这个物品的容量要小,那么这个物品可以直到取完,相当于完全背包
{
CompletePack(cost,wei);
return ;
}
else//否则就将多重背包转化为01背包
{
int k = 1;
while(k<=cnt)
{
ZeroOnePack(k*cost,k*wei);
cnt = cnt-k;
k = 2*k;
}
ZeroOnePack(cnt*cost,cnt*wei);
}
}
int main()
{
int n;
while(~scanf("%d%d",&n,&v),n+v)
{
int i;
for(i = 0;i<n;i++)
scanf("%d",&c[i]);
for(i = 0;i<n;i++)
scanf("%d",&w[i]);
memset(dp,0,sizeof(dp));
for(i = 0;i<n;i++)
{
MultiplePack(c[i],c[i],w[i]);
}
int sum = 0;
for(i = 1;i<=v;i++)
{
if(dp[i]==i)
{
sum++;
}
}
printf("%d\n",sum);
}
return 0;
}
- 做过。。。看之前的博客吧
- 代码,这次是直接手写的多重背包转化成01背包,不用模板的
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int v[5005];
int dp[255555];
int main()
{
int n;
int cnt;
while(~scanf("%d",&n))
{
if(n<=0) return 0;
int val,c;
cnt = 0;
int sum = 0;
for(int i = 0; i < n; i++){
scanf("%d%d",&val,&c);
sum+=val*c;
while(c--){
v[cnt++] = val;
}
}
sum = sum;
memset(dp,0,sizeof(dp));
for(int i = 0; i < cnt; i++){
for(int j = sum/2; j >= v[i]; j--){
dp[j] = max(dp[j],dp[j-v[i]]+v[i]);
}
}
printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);
}
return 0;
}
水dp第二天(背包有关)的更多相关文章
- hdu1114 Piggy-Bank (DP基础 完全背包)
链接:Piggy-Bank 大意:已知一只猪存钱罐空的时候的重量.现在的重量,已知若干种钱的重量和价值,猪里面装着若干钱若干份,求猪中的钱的价值最小值. 题解: DP,完全背包. g[j]表示组成重量 ...
- CodeForces 706C Hard problem (水DP)
题意:对于给定的n个字符串,可以花费a[i] 将其倒序,问是否可以将其排成从大到小的字典序,且花费最小是多少. 析:很明显的水DP,如果不是水DP,我也不会做.... 这个就要二维,d[2][max ...
- HDU 2084 数塔 (水DP)
题意:.... 析:从下往上算即可,水DP. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #incl ...
- hdu 2571 命运(水DP)
题意: M*N的grid,每个格上有一个整数. 小明从左上角(1,1)打算走到右下角(M,N). 每次可以向下走一格,或向右走一格,或向右走到当前所在列的倍数的列的位置上.即:若当前位置是(i,j), ...
- dp之分组背包hdu3033 最少取1次的解法(推荐)
题意:有n双鞋子,m块钱,k个品牌,(一个品牌可以有多种价值不同的鞋子),接下来n种不同的鞋子,a为所属品牌,b为要花费的钱,c为所能得到的价值.每种价值的鞋子只会买一双,有个人有个伟大的梦想,每个品 ...
- Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]
题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...
- POJ3211 Washing Clothes[DP 分解 01背包可行性]
Washing Clothes Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 9707 Accepted: 3114 ...
- hdu 5185 dp(完全背包)
BC # 32 1004 题意:要求 n 个数和为 n ,而且后一个数等于前一个数或者等于前一个数加 1 ,问有多少种组合. 其实是一道很水的完全背包,但是没有了 dp 的分类我几乎没有往这边细想,又 ...
- hdu2602 DP (01背包)
题意:有一个容量 volume 的背包,有一个个给定体积和价值的骨头,问最多能装价值多少. 经典的 01 背包问题不谈,再不会我就要面壁了. 终于有一道题可以说水过了 ……心好累 #include&l ...
随机推荐
- iView的使用【小白向】
首先看这篇:构建Vue本地开发环境(现阶段还不知道怎么用CDN的方式做...) 安装iView(WindowsPowershell或cmd下用cnpm) 编辑上一篇博客创建的Vue工程 先到main. ...
- input 上传图片显示预览、调用摄像头,ios和Android的兼容性解决
html代码: <img id="pic" src="img/pic.png"/> </span><input id=" ...
- 【liferay】2、可配置portlet
定义:edit和config模式一般没有使用,对于使用editor和config等模式的portlet,我们可以将他们称为可配置portlet. 我们先新建一个portlet项 添加可配置的控制元素, ...
- Ascall 码特殊字符——去除从windows上传文件的^M
在windows上编辑过的文件如果传到unix上,在每个文件的末尾都会有一个换行控制符^M,这个字符一般处于隐藏状态,除非cat -A才能看到,如果不去掉这个符号,很多脚本不能正常运行,很多文件不能正 ...
- Ajax同源和跨域
ajax跨域访问 客户端页面 var url = "http://172.16.91.121:81/FellIn/FellIn.aspx?Action=WXSave&WX_Store ...
- java多线程(六)-线程的状态和常用的方法
一个线程可以处于以下几种状态之一: (1) 新建(new):当线程被创建时,它只会短暂的处于这种状态,此时它已经获得了必须的系统资源,并执行了初始化,该线程已经有资格获取cpu时间了,之后它将转化为可 ...
- vue:简单方法替代vuex或者bus
兄弟组件,隔代组件传值很麻烦,方法虽然多,但都各有缺点. vuex: 适合数据量大,并且函数集中处理. bus:适合数据虽少,却不得不用的时候,维护困难. root:这儿指将值挂在root组件上,需要 ...
- Hibernate学习笔记(4)---hibernate的核心接口
Configuration类 该类主要是读取配置文件,启动hibernate,并负责管理hibernate的配置信息,一个程序只创建一个Configuration对象. Configuration类操 ...
- springboot mybatis 事务管理
本文主要讲述springboot提供的声明式的事务管理机制. 一.一些概念 声明式的事务管理是基于AOP的,在springboot中可以通过@Transactional注解的方式获得支持,这种方式的优 ...
- ts中interface与class的区别
interface -- 接口只声明成员方法,不做实现. class -- 类声明并实现方法. 那么接口有什么用呢?设想如下需求: 要实现一个print函数,它将传入的对象打印出来.在实际实现上,它将 ...