Codeforces K. Shaass and Bookshelf(动态规划三元组贪心)
题目描述:
B. Shaass and Bookshe
time limit per test 2 seconds
memory limit per test 256 megabytes
input standard input
output standard output
Shaass has n books. He wants to make a bookshelf for all his books. He wants the bookshelf's dimensions to be as small as possible. The thickness of thei-th book isti and its pages' width is equal towi. The thickness of each book is either1 or2. All books have the same page heights.
Shaass puts the books on the bookshelf in the following way. First he selects some of the books and put them vertically. Then he puts the rest of the books horizontally above the vertical books. The sum of the widths of the horizontal books must be no more than the total thickness of the vertical books. A sample arrangement of the books is depicted in the figure.
Help Shaass to find the minimum total thickness of the vertical books that we can achieve.
Input
The first line of the input contains an integer n,(1 ≤ n ≤ 100). Each of the nextn lines contains two integersti andwi denoting the thickness and width of thei-th book correspondingly, (1 ≤ ti ≤ 2, 1 ≤ wi ≤ 100).
Output
On the only line of the output print the minimum total thickness of the vertical books that we can achieve.
Sample test(s)
Input
5
1 12
1 3
2 15
2 5
2 1
Output
5
Input
3
1 10
2 1
2 4
Output
3
思路:
题目是要把书要么横着放,要么竖着放,要求在横着放的宽度不大于竖着放的宽度下的数着宽度的最小值。
刚开始:既然是DP,我就设状态,dp[i][j]表示放前i本书,横着放的宽度不大于j的情况下的,竖着宽度的最小值。
状态出来了,那我就转移吧。dp[i][j] = dp[i-1][j]+v[i](表示第i本书我竖着放),dp[i][j] = min(dp[i][j],dp[i][j]-w[i])(表示第i本书我横着放)。
但是,有问题,这样做求不出正确答案,因为不一低满足上面的数的长度小于等于下面的书的长度,最后就算在dp[n][i]中找满足条件的,但在dp数组计算过程中就可能已经把正确答案消掉了。(如果有dalao是类似于这种定义dp做出来的,请不吝赐教,欢迎留言)
然后:改一种定义方法:dp[i][j]表示当前放低i本书,竖着放的长度是j的情况下,横着放的长度的最小值,转移方程是,dp[i][j] = dp[i-1][j]+w[i](我横着放),dp[i][j]=min(dp[i][j],dp[i-1][j-v[i]])(我竖着放)
最后在dp[n][i]里找满足条件的最小i,就是解
代码:
#include <iostream>
#include <memory.h>
#define max_n 105
#define INF 0x3f3f3f3f
using namespace std;
int w[max_n];
int v[max_n];
int dp[max_n][max_n*];
int n;
int C = ;
int main()
{
cin >> n;
for(int i = ;i<=n;i++)
{
cin >> v[i] >> w[i];
C+=v[i];
}
memset(dp,0x3f,sizeof(dp));
dp[][] = ;
/*for(int i = 0;i<=n;i++)
{
for(int j = 0;j<=C;j++)
{
cout << dp[i][j] << " ";
}
cout << endl;
}*/
int tot = ;
for(int i = ;i<=n;i++)
{
tot+=v[i];
for(int j = ;j<=tot;j++)
{
dp[i][j] = dp[i-][j]+w[i];
if(j>=v[i]) dp[i][j] = min(dp[i][j],dp[i-][j-v[i]]);
}
}
/*for(int i = 0;i<=n;i++)
{
for(int j = 0;j<=C;j++)
{
cout << dp[i][j] << " ";
}
cout << endl;
}*/
int minm = INF;
for(int i = ;i<=C;i++)
{
if(i>=dp[n][i])
{
cout << i << endl;
break;
}
}
return ;
}
还有一种做法,好理解,但内存占用比较大,定义三元组dp[i][j][k],(还好数据小),表示放第i本书后竖着摆长度为j横着摆长度k的状态是否存在,是为1,不是为0
转移方程是在三重循环下,if(j>=v[j]&&dp[i-1][j-v[i]][k]) dp[i][j][k] = 1;if(k>w[i]&&dp[i][j][k-w[i]) dp[i][j][k] = 1;
最后遍历一遍找最小的满足dp[n][j][k]的j
代码:
#include <iostream>
#include <memory.h>
#define max_n 105
#define INF 0x3f3f3f3f
using namespace std;
int w[max_n];
int v[max_n];
int dp[max_n][max_n*][max_n*];
int n;
int C = ;
int main()
{
cin >> n;
for(int i = ;i<=n;i++)
{
cin >> v[i] >> w[i];
C+=v[i];
}
dp[][][] = ;
for(int i = ;i<=n;i++)
{
for(int j = ;j<=C;j++)
{
for(int k = ;k<=;k++)
{
if(j>=v[i]&&dp[i-][j-v[i]][k])
{
dp[i][j][k] = ;
}
if(k>=w[i]&&dp[i-][j][k-w[i]])
{
dp[i][j][k] = ;
}
}
}
}
int flag = ;
for(int j = ;j<=C&&flag;j++)
{
for(int k = ;k<=j&&flag;k++)
{
if(dp[n][j][k])
{
cout << j << endl;
flag = ;
}
}
}
return ;
}
最后,听说可以用贪心来枚举做哦,试一试。因为书的厚度只有两种,1或2,那么将书分类,在每一类中以书的宽度降序排序,最后要使竖着放的宽度最小,就把每类书的前i,j本书竖着放(因为宽度相对大)二重循环枚举出所有i,j,求满足条件的最小值。编码5分钟,调bug两小时,,,结果发现错在了cmp函数上,合着sort的cmp和qsort的还不一样啊,还有就是求和数组的下标让我疯狂。((╯‵□′)╯︵┻━┻)
代码:
#include <iostream>
#include <algorithm>
#define max_n 105
#define INF 0x3f3f3f3f
using namespace std;
int n;
struct book
{
int v;
int w;
};
book bk1[max_n];
book bk2[max_n];
int cnt1 = ;
int cnt2 =;
int sum1[max_n];//记录前i本1类书宽度和
int sum2[max_n];//记录前i本2类书宽度和
int cmp(book a,book b)
{
return a.w>b.w;
}
int main()
{
cin >> n;
int v,w;
for(int i = ;i<n;i++)
{
cin >> v >> w;
if(v==)
{
bk1[cnt1].v = v;
bk1[cnt1].w = w;
cnt1++;
}
if(v==)
{
bk2[cnt2].v = v;
bk2[cnt2].w = w;
cnt2++;
}
}
//cout << cnt1 << " " << cnt2 << endl;
sort(bk1,bk1+cnt1,cmp);
sort(bk2,bk2+cnt2,cmp);
/*for(int i = 0;i<cnt2;i++)
{
cout << bk2[i].w << " " << endl;
}*/
sum1[] = ;
sum1[] = bk1[].w;
for(int i = ;i<=cnt1;i++)
{
sum1[i] = sum1[i-]+bk1[i-].w;
}
sum2[] = ;
sum2[] = bk2[].w;
for(int i = ;i<=cnt2;i++)
{
sum2[i] = sum2[i-]+bk2[i-].w;
}
//cout << sum1[cnt1] << " and " << sum2[cnt2] << endl;
int sum = ;
int ans = INF;
for(int i = ;i<=cnt1;i++)
{
for(int j = ;j<=cnt2;j++)
{
sum = i+*j;
w = sum1[cnt1]-sum1[i]+sum2[cnt2]-sum2[j];
//cout << "i " << i << " j " << j << " sum " << sum << " w " << w << endl;
if(w<=sum&&sum<ans)
{
ans = sum;
}
}
}
cout << ans << endl;
return ;
}
Codeforces K. Shaass and Bookshelf(动态规划三元组贪心)的更多相关文章
- CodeForces 294B Shaass and Bookshelf 【规律 & 模拟】或【Dp】
这道题目的意思就是排两排书,下面这排只能竖着放,上面这排可以平着放,使得宽度最小 根据题意可以得出一个结论,放上这排书的Width 肯定会遵照从小到大的顺序放上去的 Because the total ...
- Codeforces 294B Shaass and Bookshelf:dp
题目链接:http://codeforces.com/problemset/problem/294/B 题意: 有n本书,每本书的厚度为t[i],宽度为w[i] (1<=t[i]<=2, ...
- Codeforces 294B Shaass and Bookshelf(记忆化搜索)
题目 记忆化搜索(深搜+记录状态) 感谢JLGG //记忆话搜索 //一本书2中状态,竖着放或者横着放 //初始先都竖着放,然后从左边往右边扫 #include<stdio.h> #inc ...
- Codeforces Round #178 (Div. 2) B. Shaass and Bookshelf —— DP
题目链接:http://codeforces.com/contest/294/problem/B B. Shaass and Bookshelf time limit per test 1 secon ...
- 【CF1097E】Egor and an RPG game(动态规划,贪心)
[CF1097E]Egor and an RPG game(动态规划,贪心) 题面 洛谷 CodeForces 给定一个长度为\(n\)的排列\(a\),定义\(f(n)\)为将一个任意一个长度为\( ...
- 【CF183D】T-shirt(动态规划,贪心)
[CF183D]T-shirt(动态规划,贪心) 题面 洛谷 CodeForces 题解 \(O(n^2m)\)的暴力懒得写了,比较容易,可以自己想想. 做法是这样的,首先我们发现一个结论: 对于某个 ...
- 【BZOJ1046】上升序列(动态规划,贪心)
[BZOJ1046]上升序列(动态规划,贪心) 题面 BZOJ 洛谷 题解 我一开始看错题了,一度以为是字典序最小的序列. 最后发现它要求的字典序是位置的字典序最小. 那就很好办了. 设\(f[i]\ ...
- POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心)-动态规划做法
POJ 3659 Cell Phone Network / HUST 1036 Cell Phone Network(最小支配集,树型动态规划,贪心) Description Farmer John ...
- 【CF1133E】K Balanced Teams(动态规划,单调队列)
[CF1133E]K Balanced Teams(动态规划,单调队列) 题面 CF 让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素 ...
随机推荐
- Oracle-关于Oracle.ManagedDataAccess
今天调用webservice的时候,运行程序后开始报错以下的错误信息 “/”应用程序中的服务器错误. 未能加载文件或程序集“Oracle.DataAccess”或它的某一个依赖项.试图加载格式不正确的 ...
- .Net Core 定时任务TimeJob
转载自:https://blog.csdn.net/u013711462/article/details/53449799 定时任务 Pomelo.AspNetCore.TimedJob Pomelo ...
- 【视频开发】【CUDA开发】英伟达CUVID硬解,并通过FFmpeg读取文件
虽然FFmpeg本身有cuvid硬解,但是找不到什么好的资料,英伟达的SDK比较容易懂,参考FFmpeg源码,将NVIDIA VIDEO CODEC SDK的数据获取改为FFmpeg获取,弥补原生SD ...
- Springboot项目中异常拦截设计与处理
背景: 项目运行过程中会出现各种各样的问题,常见的有以下几种情况: 业务流程分析疏漏,对业务流程的反向操作.边界分析设计不充分 调用外部服务.调用外部系统出现的超时.错误.返回值与预期不符 外部资源连 ...
- SpringBoot+Mybatis+MySql 自动生成代码 自动分页
一.配置文件 <!-- 通用mapper --> <dependency> <groupId>tk.mybatis</groupId> <arti ...
- php_mvc实现步骤六
shop34-1-目录布局 存在项目的根目录 shop34 框架代码与应用程序代码划分 框架代码: 在各个应用程序间可以通用的代码. 应用程序代码: 当前项目的业务逻辑实现的代码. 分别创建两个子目录 ...
- Centos安装nodejs,并运行项目
不建议编译安装,对gcc要求比较高 安装nodejs yum install nodejs nodejs升级 npm i -g n --force n stable npm升级 npm install ...
- 「CTS2019」氪金手游
「CTS2019」氪金手游 解题思路 考场上想出了外向树的做法,居然没意识到反向边可以容斥,其实外向树会做的话这个题差不多就做完了. 令 \(dp[u][i]\) 表示单独考虑 \(u\) 节点所在子 ...
- Debian 下忘记root密码的特殊修改方式
当系统开机进入 grub页面时,在启动条目上按下键盘的 e 进入编辑 找到 linux 开头的一行,类似下面这样 linux /boot/vmlinux-4.9.0.8-amd64 root=/dev ...
- WPF内嵌网页的两种方式
在wpf程序中,有时会内嵌网页.内嵌网页有两种方法,一种是使用wpf自带WebBrowser控件来调用IE内核,另一种是使用CefSharp包来调用chrom内核. 一.第一种使用自带WebBrows ...