3598: [Scoi2014]方伯伯的商场之旅

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 449  Solved: 254
[Submit][Status][Discuss]

Description

方伯伯有一天去参加一个商场举办的游戏。商场派了一些工作人员排成一行。每个人面前有几堆石子。说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的第 j 位。
现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 L,R。方伯伯要把位置在 [L, R]
中的每个人的石子都合并成一堆石子。每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量 *
移动的距离。商场承诺,方伯伯只要完成任务,就给他一些椰子,代价越小,给他的椰子越多。所以方伯伯很着急,想请你告诉他最少的代价是多少。
例如:10 进制下的位置在 12312 的人,合并石子的最少代价为:
1 * 2 + 2 * 1 + 3 * 0 + 1 * 1 + 2 * 2 = 9
即把所有的石子都合并在第三堆

Input

输入仅有 1 行,包含 3 个用空格分隔的整数 L,R,K,表示商场给方伯伯的 2 个整数,以及进制数

Output

输出仅有 1 行,包含 1 个整数,表示最少的代价。

Sample Input

3 8 3

Sample Output

5

HINT

1 < =  L < =  R < =  10^15, 2 < =  K < =  20

Source

一眼数位DP,但是具体实现感觉非常难以理解。

主要思路是:先默认每个人都将式子移到最低的那一位上去,然后从2开始枚举如果将其中一些人的石子从i-1移到i最终结果会优多少。

第一个DP就是普通的数位DP,但是第二个DP就有一个很难处理的问题:如何确定到底那些人的石子可以(或需要)从i-1移到i,因为每个人最终所选的那一位都不同。

这里有一种新型的记忆化搜索,dfs(i,sum,lim)表示(从高到低)前i位将(那些可以或需要移动的)人移动,且前i位已经变优了sum,所能得到的最终解(也就是最后最多能变优多少)。一般记搜都是形如dfs(i)+=dfs(i+1)+f(i)的(最终返回的sum),但这种记搜是dfs(i,sum,lim)+=dfs(i+1,sum+f[i],lim')(最终返回的仍然是sum,只是在递归底层被处理过的sum)。也就是说,普通记搜记录的是这个状态到目标状态(递归底层)的信息,而这种记录的是初始状态到这个状态的信息。

这种记搜实际上不应该从DP的角度去理解,而是应该从搜索的角度,实际上就是一个记录了中间状态(sum)的搜索,在底层进行处理。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define ll long long
using namespace std; int k,num[];
ll l,r,len,f[][**][]; ll dfs1(int pos,int sum,bool lim){
if (pos>len) return sum;
if (f[pos][sum][lim]!=-) return f[pos][sum][lim];
ll res=; int end=(lim?num[pos]:k-);
rep(i,,end) res+=dfs1(pos+,sum+i*(pos-),lim && (i==end));
return f[pos][sum][lim]=res;
} ll dfs2(int pos,int sum,int m,bool lim){
if (pos>len) return max(sum,);
if (f[pos][sum][lim]!=-) return f[pos][sum][lim];
ll res=; int end=(lim?num[pos]:k-);
rep(i,,end) res+=dfs2(pos+,sum+((pos<m)?-i:i),m,lim && (i==end));
return f[pos][sum][lim]=res;
} ll solve(ll n){
len=; while (n) num[++len]=n%k,n/=k;
reverse(num+,num+len+);
memset(f,-,sizeof(f));
ll res=dfs1(,,);
rep(i,,len) memset(f,-,sizeof(f)),res-=dfs2(,,i,);
return res;
} int main(){
freopen("bzoj3598.in","r",stdin);
freopen("bzoj3598.out","w",stdout);
scanf("%lld%lld%d",&l,&r,&k);
printf("%lld\n",solve(r)-solve(l-));
return ;
}

[BZOJ3598][SCOI2014]方伯伯的商场之旅(数位DP,记忆化搜索)的更多相关文章

  1. bzoj 3598 [Scoi2014]方伯伯的商场之旅——数位dp

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598 TJ:https://www.cnblogs.com/Zinn/p/9351218.h ...

  2. BZOJ3598 SCOI2014方伯伯的商场之旅(数位dp)

    看到数据范围就可以猜到数位dp了.显然对于一个数最后移到的位置应该是其中位数.于是考虑枚举移到的位置,那么设其左边和为l,左右边和为r,该位置数为p,则需要满足l+p>=r且r+p>=l. ...

  3. bzoj3598 [Scoi2014]方伯伯的商场之旅

    数位dp,我们肯定枚举集合的位置,但是如果每次都重新dp的话会很麻烦,所以我们可以先钦定在最低位集合,dp出代价,然后再一步步找到正确的集合点,每次更改的代价也dp算就好了. #include < ...

  4. 2019.03.28 bzoj3598: [Scoi2014]方伯伯的商场之旅(带权中位数+数位dp)

    传送门 题意咕咕咕自己读吧挺简单的 思路: 由带权中位数的性质可以得到对于每个数放在每个二进制位的代价一定是个单调或者单峰函数,因此我们先把所有的数都挪到第一个位置,然后依次向右枚举峰点(极值点)把能 ...

  5. bzoj 3598 [ Scoi 2014 ] 方伯伯的商场之旅 ——数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3598 数位DP...东看西看:http://www.cnblogs.com/Artanis/ ...

  6. 洛谷P3286 [SCOI2014]方伯伯的商场之旅

    题目:洛谷P3286 [SCOI2014]方伯伯的商场之旅 思路 数位DP dalao说这是数位dp水题,果然是我太菜了... 自己是不可能想出来的.这道题在讲课时作为例题,大概听懂了思路,简单复述一 ...

  7. 【bzoj3598】: [Scoi2014]方伯伯的商场之旅

    Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...

  8. 【bzoj3598】 Scoi2014—方伯伯的商场之旅

    http://www.lydsy.com/JudgeOnline/problem.php?id=3598 (题目链接) 题意 Solution 原来这就是极水的数位dp,呵呵= =,感觉白学了.htt ...

  9. [SCOI2014]方伯伯的商场之旅

    Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...

随机推荐

  1. 详解H5中的history单页面,手动实现单页面开发,细说h5单页面原理

    就目前来看,前端的单页面开发占了很大一部分,一方面无刷新的切换增强了体验,并且浏览器记录依然存在,前进后退都没问题,在之前我们通地址栏中的hash改变来触发onhashchange方法来实现单页面应用 ...

  2. php的发展历史

    php最初就是为了快速构建一个web页面而迅速被大家广为接受的.它的好处是在代码中能内嵌html的代码,从而让程序员能再一个页面中同时写html代码和php代码就能生成一个web页面. 这篇文章用时间 ...

  3. Java企业级电商项目架构演进之路 Tomcat集群与Redis分布式

    史诗级Java/JavaWeb学习资源免费分享 欢迎关注我的微信公众号:"Java面试通关手册"(坚持原创,分享各种Java学习资源,面试题,优质文章,以及企业级Java实战项目回 ...

  4. Linux实用命令之xdg-open

    为什么要介绍 xdg-open 呢,得先从需求说起. 一般在控制台中,可以使用命令操作各式文本文件.但难以避免,需要操作一些非文本文件,如 pdf,doc 等. 此时,一般的做法是,打开文件管理器,再 ...

  5. 用C++写程序的一些感悟

    前言 近期使用C++有了一些心得很感悟,这里整理一下. 心得1 如果只会使用LabVIEW写程序,还想要进一步深入程序设计,一定要学习一门文本语言. 什么是会用LabVIEW 会用是个比较笼统的概念. ...

  6. Feign 发送对象,对象含多个文件

    Feign在发送文件时,可以使用Feign-form. 另一种方式,关键就是,要将文件转成Resource,然后使用Spring的MultivalueMap 本次发送的是个对象,对象里含有 文件对象数 ...

  7. Linux时间结构体和获得时间函数

    关于Linux下时间编程的问题: 1. Linux下与时间有关的结构体 struct timeval { int tv_sec; int tv_usec; }; 其中tv_sec是由凌晨开始算起的秒数 ...

  8. leetcode 之Remove Duplicates from Sorted Array(2)

    描述    Follow up for ”Remove Duplicates”: What if duplicates are allowed at most twice?    For exampl ...

  9. hdu 5918(强行水过去..正解KMP)

    Sequence I Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  10. hexdump related.

    hexdump format strings Tue 13 December 2005 In tips. Ian Wienand More from the "things you'd le ...