VIJOS1392拼拼图的小杉
来源:互联网 发布:一天淘宝刷3单会封号吗 编辑:程序博客网 时间:2024/04/27 13:39
题目大意
给定n个数,将这n个数中的一些依次放进m个集合,每个集合中所有数的和不能超过T。集合包含的元素不能交叉,也就是说如果第1个数和第3个数放入了集合1,那么第2个数要么放入集合1,要么不放入任何一个集合。
求m个集合中最多能包含多少个数
1<=n,m,T<=1000
分析
来源于题解中小岛的想法
这题如果状态直接定义为f[i,j]=x表示前i个数放入j个集合最多能包含x个数
那么操作起来会比较困难,所有应换一种状态的定义。
记a[i]为第i个数,f[i,j]=(t,s)表示前i个数选了j个数需要t个集合,最后一个集合所有数之和为s,那么
f[i,j]=min{f[i-1,j],f[i-1,j-1]+a[i]}
f[0,0]=(1,0)
那么就是一个0-1背包问题啦
最后的答案是使得f[n,i]的t<=m的最大的i
代码
#include<cstdio>const int maxn=1000;int n,m,T,a[maxn+10];struct node{ int t,s; bool operator < (const node d) const{ if (t<d.t) return 1; if (t>d.t) return 0; return s<d.s; } node operator + (const int d) const{ if (s+d<=T) return (node){t,s+d}; else return (node){t+1,d}; }};node f[maxn+10];int main(){ scanf("%d%d%d",&n,&m,&T); node te; for (int i=1;i<=n;i++) scanf("%d",&a[i]); f[0].t=1; for (int i=1;i<=n;i++){ f[i]=f[i-1]+a[i]; for (int j=i-1;j>=1;j--){ te=f[j-1]+a[i]; if (te<f[j]) f[j]=te; } } for (int i=n;i>=0;i--) if (f[i].t<=m){ printf("%d\n",i); return 0; }}
0 0
- VIJOS1392拼拼图的小杉
- 8.17 拼拼图的小杉 1536
- 今日小程序推荐:功夫拼图-"爱"TA就给TA拼
- 小TIPS:合拼gridview的header
- 小TIPS:合拼gridview的header
- 基于IOS平台的游戏之小拼图
- 第二个小项目 - 拼图
- 程序员的“拼图”游戏
- 不可还原的拼图
- 不可还原的拼图
- 漂亮的字符拼图
- 好友拼图的原理
- 不可还原的拼图
- 拼图
- 拼图
- 拼图
- 拼图
- 拼图
- 3631: [JLOI2014]松鼠的新家
- Objective-C 字典:"NSDictionary" 和 "NSMutableDictionary"
- IIS端口被占用
- 【杭电】[2019]数列有序!
- pojCuring 2.0(dfs)
- VIJOS1392拼拼图的小杉
- 2015年的我
- PHP数据库操作类封装
- I/O端口和I/O内存--学习备忘
- 【软件工程】5.svn启动、注册服务器端
- Win 10 下安装Genymotion和CirtualBox 教程
- UISearchDisplayController实现搜索功能
- zabbix安装
- scala-32:List的基本操作实战与基于模式匹配的List排序算法实现