UVALive 4031 Integer Transmission(贪心 + DP)
分析:求出最大值和最小值比较简单,使用贪心法,求最小值的时候我们让所有的0尽可能的向后延迟就可以了,求最大值则相反。 关键在于求出可以组合出的数字个数。
这就是组合数学版的dp了,我们让dp[i][j]表示当前i个0,和前j个1被接收后所能形成的数字个数,初始条件为dp[0][0] = 1; 决策有两种,第一种转移到dp[i+1][j]也就是多接收一个0,这时候定义F1[]数组记录1的发送时间,F0[]数组记录0的发送时间,那么如上方程的转移条件为 F1[j+1]+d >= F0[i+1],也就是第i+1个0能先于第j+1个1被接收。另一种转移到dp[i][j+1],也是一样的道理。最后注意一下边界的特判,dp[sum0][sum1]就是答案。
注意: 关于上述方法有人可能会问,我们在同一时刻接收到了多个数字,按照题目要求应该自由排列,为什么上述方法,完全没有体现到这一点呢? 不要被迷惑了,我们关心的是多少个1和0被接收,而不是哪个1先被接收,我们的循环里完全记录下了各种情况的个数。
坑点:这个题的数组范围很大,如果不用unsighed long long,就会爆long long,我也因为这个WA了很多次。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define LL unsigned long long
#define N 70
int n,d,bit[N];
struct ID{
int s1,s0;
}id[N];
LL k;
void Get_Bit(){
LL tmp = k;
int ip = ;
memset(bit,,sizeof(bit));
while(tmp)
{
if(tmp&) bit[ip] = ;
ip++;
tmp >>= ;
}
}
LL mypow(int x){
LL tmp = ;
for(int i = ;i <= x;i++) tmp *= ;
return tmp;
}
LL Get_Min(){
for(int i = ;i <= n;i++){
if(bit[i]) {id[i].s1 = ; id[i].s0 = ;}
else {id[i].s0 = ; id[i].s1 = ;}
}
for(int i = n;i >= ;i--){
if(bit[i]){
id[i].s1--;
if(i-d >= ) id[i-d].s1++;
else id[].s1++;
}
}
LL Min = ;
int ip = ;
for(int i = ;i <= n;i++){
while(id[i].s1 > ) {Min += mypow(ip); id[i].s1--; ip++;}
while(id[i].s0 > ) {ip++; id[i].s0--;}
}
// cout<<"MIN = "<<Min<<endl;
return Min;
}
LL Get_Max(){
for(int i = ;i <= n;i++){
if(bit[i]) {id[i].s1 = ; id[i].s0 = ;}
else {id[i].s0 = ; id[i].s1 = ;}
}
for(int i = n;i >= ;i--){
if(bit[i]==){
id[i].s0--;
if(i-d >= ) id[i-d].s0++;
else id[].s0++;
}
}
LL Max = ;
int ip = ;
for(int i = ;i <= n;i++){
while(id[i].s0 > ) {id[i].s0--; ip++;}
while(id[i].s1 > ) {Max += mypow(ip); ip++; id[i].s1--;}
}
// cout<<"MAX = "<<Max<<endl;
return Max;
}
LL Get_Ans(){
LL dp[N][N];
int sum0=,sum1=,f1[N],f0[N];
memset(dp,,sizeof(dp));
for(int i = n;i >= ;i--){
if(bit[i]) f1[++sum1] = n-i+;
else f0[++sum0] = n-i+;
}
dp[][] = ;
for(int i = ;i <= sum0;i++){
for(int j = ;j <= sum1;j++){
if(j == sum1 && i < sum0) dp[i+][j] += dp[i][j];
if(i == sum0 && j < sum1) dp[i][j+] += dp[i][j];
if(i==sum0 || j==sum1) continue;
if(f1[j+]+d >= f0[i+]) dp[i+][j] += dp[i][j];
if(f0[i+]+d >= f1[j+]) dp[i][j+] += dp[i][j];
}
}
return dp[sum0][sum1];
}
int main()
{
LL Min,Max,ans,ca=;
while(cin>>n){
if(n==) break;
cin>>d>>k;
Get_Bit();
Min = Get_Min();
Max = Get_Max();
ans = Get_Ans();
cout<<"Case "<<++ca<<": "<<ans<<" "<<Min<<" "<<Max<<endl;
}
return ;
}
UVALive 4031 Integer Transmission(贪心 + DP)的更多相关文章
- 【BZOJ-3174】拯救小矮人 贪心 + DP
3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 686 Solved: 357[Submit][Status ...
- BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP
BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...
- 洛谷P4823 拯救小矮人 [TJOI2013] 贪心+dp
正解:贪心+dp 解题报告: 传送门! 我以前好像碰到过这题的说,,,有可能是做过类似的题qwq? 首先考虑这种显然是dp?就f[i][j]:决策到了地i个人,跑了j个的最大高度,不断更新j的上限就得 ...
- 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp
题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...
- 【bzoj3174】[Tjoi2013]拯救小矮人 贪心+dp
题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人,我们知道他从脚 ...
- hdu 1257 最少拦截系统【贪心 || DP——LIS】
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- 贪心+DP【洛谷P4823】 [TJOI2013]拯救小矮人
P4823 [TJOI2013]拯救小矮人 题目描述 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以 ...
- 贪心+dp
贪心+dp 好多题都是这个思想, 可以说是非常重要了 思想一: 在不确定序列无法dp的情况下, 我们不妨先假设序列已经选定, 而利用贪心使序列达到最优解, 从而先进行贪心排序, 在进行dp选出序列 思 ...
- 【题解】CF1056F Write the Contest(三分+贪心+DP)
[题解]CF1056F Write the Contest(三分+贪心+DP) 最优化问题的三个解决方法都套在一个题里了,真牛逼 最优解应该是怎样的,一定存在一种最优解是先完成了耗时长的任务再干别的( ...
随机推荐
- 关于如何用Jquery监听鼠标滚轮改变横向滚动条
$(function(){ if ((navigator.userAgent.indexOf('MSIE') >= 0)){/*判断是否是IE浏览器*/ var scroll_width = 1 ...
- Java Tcp文件传输---转载
/** 客户端 1.服务端点 2.读取客户端已有的文件数据 3.通过socket输出流发给服务端 4.读取服务端反馈信息 5.关闭 **/ import java.io.*; import java. ...
- Openjudge-计算概论(A)-找和为K的两个元素
描述: 在一个长度为n(n < 1000)的整数序列中,判断是否存在某两个元素之和为k. 输入第一行输入序列的长度n和k,用空格分开.第二行输入序列中的n个整数,用空格分开.输出如果存在某两个元 ...
- Program Files 与Program Files (x86)
在64位系统下,为了更好的兼容32位程序,在安装一些32位程序(注意某些程序他就是32位的),会默认扔到program files(x86)这个文件夹下,而一些64位的程序,或程序本身没有位数区别的, ...
- shell笔记-local、export用法
local一般用于局部变量声明,多在在函数内部使用. 1. Shell脚本中定义的变量是global的,其作用域从被定义的地方开始,到shell结束或被显示删除的地方为止. 2. ...
- linux zeromq
本人在centos下安装zeromq 1.下载最新版的zeromq http://download.zeromq.org/ 2 解压 tar -xvf zeromq-3.1.0-beta.tar.gz ...
- hdu5573 二叉树找规律,二进制相关
input T 1<=T<=100 n k 1<=n<=1e9 n<=2^k<=2^60 output 从1走到第k层,下一层的数是上一层的数×2或者×2+1,每 ...
- 慎用#define
#define INT_MAX 2147483647 INT_MAX+1 就会变成负数 long long r; r > INT_MAX+1 就会出错,应该写成 r > 21474 ...
- Redis简介一
Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高并发的应用场景.Redis纯粹为应用而产生,它是一个高性能的key-valu ...
- keybd_event 对应表
Option Explicit Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bSc ...