卧薪尝胆,厚积薄发。
SCOI2014 方伯伯的商场之旅
Date: Sun May 27 01:42:52 CST 2018 In Category: NoCategory

Description:

第 $i$ 个人的第 $j$ 堆石子个数是 $i$ 的 $K$ 进制下的第 $j$ 位,把第 $[L,R]$ 个人的石子全部合成一堆,代价是石子数量 $\times$ 移动距离,求最小代价。

Solution:

对于每个人是相互独立的,对于每个石子一定直接移到目的地,采取这样一种合并石子的方案:先把所有石子合并到第一堆,再依次把所有石子往后移看是否更优,采用记搜 $+$ 数位 $DP$ 的方式处理。
首先是把所有石子合并到第一堆,倒序处理 $pos$ ,记 $sum$ 表示当前移动距离和了,发现对于 $sum$ 相同的状态之后的转移也相同,于是可以以 $(pos,sum)$ 为状态记忆化,注意转移过程中 $bord$ 的处理,转移时枚举下一位是什么,其实也就是把所有状态合在一起处理提高效率。
接下来处理把所有状态往后推,枚举最终汇合点,因为要求的是更改汇合点与原答案的差,所以汇合点位置变化 $1$ 每个石子会对答案产生一单位的影响,汇合点之前的往后退一格,对于当前枚举的 $i$ ,有 $i$ 个石子需要往后推,所以 $sum+=i$ ,因为 $pos$ 倒序循环,所以 $pos\ge gather$ 的要往后推,汇合点之后的距离变少了,所以 $sum -= i$ ,如果某个状态上 $sum$ 已经小于 $0$ 了,那么之后再减一定会小于零,那么可以直接 $return$ $0$ ,由于最优点一定在中位数,所以价值单调先升后降,这次 $return$ $0$ 的之后也一定不更优,所以不用管。
注意每次像普通数位 $DP$ 一样状态只保存整块,所以对于 $bord$ 特殊处理,且不更新 $f$ 数组。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
ll l,r;
ll k;
ll f[60][3000];
int bit[60];
ll dfs(int pos,int sum,bool bord)
{
if(pos == 0)return sum;
if(!bord && f[pos][sum] != -1)return f[pos][sum];
ll res = 0;
for(int i = 0;i <= (bord ? bit[pos] : k - 1);++i)
{
res += dfs(pos - 1,sum + i * (pos - 1),bord && (i == (bord ? bit[pos] : k - 1)));
}
if(!bord)f[pos][sum] = res;
return res;
}
ll dfs(int pos,int sum,int gather,bool bord)
{
if(sum < 0)return 0;
if(pos == 0)return sum;
if(!bord && f[pos][sum] != -1)return f[pos][sum];
ll res = 0;
for(int i = 0;i <= (bord ? bit[pos] : k - 1);++i)
{
if(pos >= gather)res += dfs(pos - 1,sum + i,gather,bord && (i == (bord ? bit[pos] : k - 1)));
else res += dfs(pos - 1,sum - i,gather,bord && (i == (bord ? bit[pos] : k - 1)));
}
if(!bord)f[pos][sum] = res;
return res;
}
ll solve(ll n)
{
int len = 0;
while(n > 0)
{
bit[++len] = n % k;
n /= k;
}
memset(f,-1,sizeof(f));
ll res = dfs(len,0,true);
for(int i = 2;i <= len;++i)
{
memset(f,-1,sizeof(f));
res -= dfs(len,0,i,true);
}
return res;
}
int main()
{
cin >> l >> r >> k;
cout << solve(r) - solve(l - 1) << endl;
return 0;
}
In tag: DP-数位DP
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡