EOJ Problem #3249 状态压缩+循环周期+反向递推
限量供应
Time limit per test: 4.0 seconds
Time limit all tests: 4.0 seconds
Memory limit: 256 megabytes
华东师大的食堂常常有许多很奇怪的菜,比方说:玉米炒葡萄、玉米炒草莓、玉米炒香蕉……所以很多同学,包括你,去食堂吃东西,是只吃菜,不吃饭的。
但这些菜都是限量供应的:如果你今天点了某一道菜,那么接下来 r 天(不包括今天)你都不能再点这道菜了。当然,同一道菜在同一天内点两份也是不可以的。此外,因为你是从来不吃饭的,所以为了保证能量充足,你每天吃的所有菜的卡路里总和必须大于等于 C。
在本学期的 m 天中,你每天都要在食堂吃。你现在既想吃得多,又不能吃得太多,所以你提出了以下两个要求:
在不违背上述条件的前提下,吃的菜的数目(不是种类数)应尽可能多;
在不违背 1 的前提下,吃的所有菜的卡路里总和应尽可能小。
Input
第一行是一个整数 T (1≤T≤100),表示测试数据组数。
接下来是 T 组测试数据,每组数据两行。
第一行四个整数 n,m,r,C (1≤n≤12,1≤m≤1000,1≤r≤20,1≤C≤105)。其中 n 表示菜的种数,其余变量含义如题中描述。
第二行 n 个整数:c1,c2,…,cn (1≤ci≤105)。
Output
对于每组数据,输出 Case x: y z
。x 表示从 1 开始的测试数据编号,y 和 z 分别表示菜的数目和卡路里总和。如果没有满足要求的方案,y 和 z 是 0 0
。
Examples
2
7 9 3 3
3 2 2 2 2 3 3
7 5 3 3
3 2 2 2 2 3 3
Case 1: 18 42
Case 2: 11 25
Source
2017 华东师范大学校赛
/**
题目:EOJ Problem #3249
链接:http://acm.ecnu.edu.cn/problem/3249/
题意:
华东师大的食堂常常有许多很奇怪的菜,比方说:玉米炒葡萄、玉米炒草莓、玉米炒香蕉……
所以很多同学,包括你,去食堂吃东西,是只吃菜,不吃饭的。
但这些菜都是限量供应的:如果你今天点了某一道菜,那么接下来 r 天(不包括今天)你都不能再点这道菜了。
当然,同一道菜在同一天内点两份也是不可以的。此外,因为你是从来不吃饭的,所以为了保证能量充足,
你每天吃的所有菜的卡路里总和必须大于等于 C。
在本学期的 m 天中,你每天都要在食堂吃。你现在既想吃得多,又不能吃得太多,
所以你提出了以下两个要求: 1,在不违背上述条件的前提下,吃的菜的数目(不是种类数)应尽可能多; 2,在不违背 1 的前提下,吃的所有菜的卡路里总和应尽可能小。
,
思路: 预处理s表示满足>=C的菜的集合。 假设总共有n个s满足条件。 那么将n个s。选出来。 排列一行,m个。 保证区间长度r+1范围内的s不能有相同的菜。满足的序列中,取菜的数目最多,然后考虑总卡路里最小。 如果能够找到这样的r+1个s。那么此后都这样循环便是最优。 20*4096 = 81920 dp[i][s]表示前i天选了s集合的菜是否成立。 dp[i][s] = dp[i-1][s']; dp[0][0] = 1; 如果m<r+1; 那么直接就可以遍历dp[m][s]中的s为真时候的s的菜数目num以及花费ans。
如果m>r+1; 遍历dp[r+1][s]中的s为真时候的s的菜数目num以及卡路里花费ans就可以知道m/(r+1)个周期结果为num*(m/(r+1)), ans*(m/(r+1));
然后还会多余m%(r+1),知道了r+1的状态s,就可以反向递推获得dp[m%(r+1)][s0]可以得到的s0(因为连续r+1天不能存在相同的,
所以受到前r+1的状态s的影响,通过反向递推解决).然后计算s0的结果加上那m/(r+1)个周期结果。
注意:r+1天算出的最优的s,不能保证通过这个s反向递推的s0是最优的。我的处理方法是:暴力所有可能的s,然后对每个s反向递推s0.
比较所有的结果中最优的。 */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <time.h>
using namespace std;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e6+;
int T, n, m, r, C;
LL cost[<<];
LL c[];
int dp[][<<];
int digit[<<];
LL num = , ans = , num1 = , ans1 = ;
void init(int n)///ok
{
int len = <<n;
for(int i = ; i < len; i++){
cost[i] = ;
digit[i] = ;
for(int j = ; j < n; j++){
if(i&(<<j)){
cost[i]+=c[j];
digit[i]++;
}
}
}
}
LL num2, ans2;
void dfs(int m,int i,int s)
{
if(i==m){
int cnt = digit[s];
if(cnt>num2){
num2 = cnt; ans2 = cost[s];
}else
{
if(cnt==num2){
if(cost[s]<ans2){
ans2 = cost[s];
}
}
}
return ;
}
for(int s0 = s; s0; s0 = (s0-)&s){
if(cost[s0]<C) continue;///比赛的时候,这道题!!!我少了这行代码。。。唉。dp[i-1][s-s0]如果为真,未必是当前这个状态到来的,
///必须加一个判断条件,判断是否可以由s到s-s0;
if(dp[i-][s-s0]){
dfs(m,i-,s-s0);
}
} }
int main()
{
cin>>T;
int cas = ;
while(T--)
{
scanf("%d%d%d%d",&n,&m,&r,&C);
for(int i = ; i < n; i++) scanf("%lld",&c[i]);
init(n);
memset(dp, , sizeof dp);
dp[][] = ;
int len = <<n;
int mis = min(r+,m);
for(int i = ; i <= mis; i++){
for(int s = ; s < len; s++){
if(cost[s]<C) continue;
for(int s0 = s; s0; s0 = (s0-)&s){
if(cost[s0]<C) continue;
dp[i][s] |= dp[i-][s-s0];
}
}
} num = , ans = ;
if(r+>=m){
for(int s = ; s < len; s++){
if(dp[m][s]){
int cnt = digit[s];
if(cnt>num){
num = cnt; ans = cost[s];
}else
{
if(cnt==num){
if(cost[s]<ans) ans = cost[s];
}
}
}
}
}else
{///m > r+1;
for(int s = ; s < len; s++){
if(dp[r+][s]){
ans1 = cost[s];
num1 = digit[s];
num1 = m/(r+)*num1;
ans1 = m/(r+)*ans1;
num2 = ans2 = ;
if(m%(r+)!=){
dfs(m%(r+),r+,s);
}
num1 += num2;
ans1 += ans2;
if(num1>num){
num = num1; ans = ans1;
}else
{
if(num1==num&&ans1<ans){
ans = ans1;
}
}
}
}
}
printf("Case %d: %lld %lld\n",cas++,num,ans);
}
return ;
}
EOJ Problem #3249 状态压缩+循环周期+反向递推的更多相关文章
- HDU 1757 A Simple Math Problem 【矩阵经典7 构造矩阵递推式】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=1757 A Simple Math Problem Time Limit: 3000/1000 MS (J ...
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 M. Frequent Subsets Problem【状态压缩】
2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 M. Frequent Subsets Problem 题意:给定N和α还有M个U={1,2,3,...N}的子集,求子集X个数,X满足:X是U ...
- 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛:Frequent Subsets Problem (状态压缩)
题目链接 题目翻译: 给出一个数n,和一个浮点数a,数n代表全集U = {1,2,...,n},然后给出 M个U的子集,如果一个集合B(是U的子集),M个集合中有至少M*a个集合包含B, 则B这个集合 ...
- poj1753 Flip Game —— 二进制压缩 + dfs / bfs or 递推
题目链接:http://poj.org/problem?id=1753 Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submis ...
- 【bzoj1076】[SCOI2008]奖励关 期望dp+状态压缩dp
题目描述 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后也不能再 ...
- C语言 分支与循环 递推思想 穷举 流程的转移控制
条件语句 开关控制语句(SWITCH语句) 象坐电梯一样,break是按的楼层,不加break则会一直执行下去. 上面程序有细节BUG,边界测试输入-5,105时由于整除会得到错误的结果. 解决方法: ...
- FZU-2218 Simple String Problem(状态压缩DP)
原题地址: 题意: 给你一个串和两个整数n和k,n表示串的长度,k表示串只有前k个小写字母,问你两个不含相同元素的连续子串的长度的最大乘积. 思路: 状态压缩DP最多16位,第i位的状态表示第i位 ...
- 旅行商问题——状态压缩DP
问题简介 有n个城市,每个城市间均有道路,一个推销员要从某个城市出发,到其余的n-1个城市一次且仅且一次,然后回到再回到出发点.问销售员应如何经过这些城市是他所走的路线最短? 用图论的语言描述就是:给 ...
- Escape(状态压缩+最大流,好题)
Escape http://acm.hdu.edu.cn/showproblem.php?pid=3605 Time Limit: 4000/2000 MS (Java/Others) Memo ...
随机推荐
- Xcode升级后导致插件不能用, 一句代码更新UUID OK~
find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth 3 | ...
- maven-pom-build
地址: http://blog.csdn.net/taiyangdao/article/details/52374125
- RocketMQ(7)——通信协议
RocketMQ(7)——通信协议 RocketMQ的通信协议其实很简单,但是无论是官方的用户手册,还是网上的博客,并没有很清晰简单地把其中所有的内容和原理讲明白. 对于需要扩展其他语言SDK的开发来 ...
- 【JSP EL】el表达式判断是否为null
后台程序放入Model中,从前台el表达式取出来非常方便,但是如果需要处理 当数据为null的时候,怎么办,不为null的时候,怎么办:这个怎么处理呢? <span class="us ...
- mongodb_性能监控
一.使用mongostat.exe cd C:\Program Files\MongoDB\Server\3.0\bin\ --> mongostat.exe --> mongostat ...
- Oracle Process Cloud流程云实践
本篇适合对Oracle Unified BPM有一定基础的人参考,本篇也是参考Oracle A-team John Featherly的文章进行的实践. 1. 流程创建 打开cloud.o ...
- Flex4以后Menubar背景设置问题
flex4的 backgroundColor失效,需要使用 contentBackgroundColor menubar.setStyle("contentBackgroundColor&q ...
- JS组件系列——自己封装一个上传文件组件
页面调用: $('#fileUpload').cemsUpload({ errorEmpty:'<s:text name="cupgrade.view.tip.upload.file. ...
- POJ 3020 Antenna Placement 最大匹配
Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6445 Accepted: 3182 ...
- Docker默认存储路径修改
Docker默认存储路径: # docker info...... Data loop file: /var/lib/docker/devicemapper/devicemapper/data.... ...