Codeforces 917C - Pollywog(状压 dp+矩阵优化)
UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊(
这是一道 *2900 的 D1C,不过还是被我想出来了
u1s1 大概是这题用到的几个套路我都见过罢
首先注意到 \(k\) 很小,故考虑状压 \(dp\),\(dp_{i,s}\) 表示当前所有 pollywog 都在编号 \([i-k+1,i]\) 范围内的石头上,并且有且仅有编号 \(i-x+1,x\in s\) 的石头上有 pollywog。
转移还是比较显然的,如果 \(k\in s\),那么我们必须强制让这个当前位于 \(i-k+1\) 位置的 pollywog 跳 \(k\) 步,否则我们可以枚举一个青蛙并让它跳到编号为 \(i+1\) 的石头上,或者干脆 \(i+1\) 位置上不放 pollywog,也就是说:
- \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_k+a_{i+1},s'=\{x+1|x\in s\land x\ne k\}\cup\{1\}(k\in s)\)
- \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_d+a_{i+1},s'=\{x+1|x\in s\land x\ne d\}\cup\{1\}(k\notin s,d\in s)\)
- \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_k,s'=\{x+1|x\in s\}(k\notin s)\)
其中 \(c_i\) 为跳 \(i\) 格所需消耗的体力,\(a_i\) 为 \(i\) 所在的特殊格所额外消耗的体力(如果 \(i\) 不是特殊格则 \(a_i=0\))。
初始 \(dp_{x,\{1,2,\dots,x\}}=0\),答案为 \(dp_{n,\{1,2,\dots,x\}}\)。
考虑优化,注意到这个 \(n\) 很大但是这个转移呈规律性。故考虑矩阵优化 \(dp\),我们把转移方程用矩阵的形式表示出来,即我们总能找到一个矩阵 \(A\) 使得 \(A\times\begin{bmatrix}dp_{i,0}\\dp_{i,1}\\\dots\\dp_{i,2^k-1}\end{bmatrix}=\begin{bmatrix}dp_{i+1,0}\\dp_{i+1,1}\\\dots\\dp_{i+1,2^k-1}\end{bmatrix}\)(其中两个大小分别为 \(n\times m,m\times k\) 的矩阵 \(A,B\) 乘法得到的矩阵 \(C\) 为 \(n\times k\) 的矩阵,且 \(C_{i,j}=\min\limits_{l=1}^mA_{i,l}+B_{l,j}\))。那么如果没有什么特殊格子的限制的话,直接一遍矩阵快速幂就行了。
接下来考虑有特殊格子的情况,我们按照 CF576D 的套路将所有特殊格子按坐标排个序,显然一个特殊格子 \((x,y)\) 对 \(dp\) 值产生的影响就是令 \(\forall 1\in S,dp_{x,S}\leftarrow dp_{x,S}+y\)。故可以直接矩阵快速幂求出 \(dp_x\),然后就直接在 \(dp_x\) 上修改贡献即可。
这个算法的复杂度 \(\omega^3p\log n\) 的,其中 \(\omega=2^k\),无法通过。
考虑优化,注意到这个转移矩阵 \(A\) 是不会发生变化的,故考虑借鉴 P6772 的套路,而我们矩阵快速幂求出 \(dp_x\) 实质上是矩阵乘向量,单次乘法复杂度为 \(\omega^2\),故考虑预处理出 \(A^{2^k}\),这样可实现 \(\omega^3\log n\) 预处理,\(\omega^2p\log n\) 矩阵快速幂。
可是这样还是会炸啊……
这里还有第三个套路,就是对于合法的 \(dp_{i,S}\) 一定有 \(|S|=x\),故合法的状态最多 \(\binom{8}{4}=70\) 种,于是可以把所有合法的状态压缩成一个 \([1,70]\) 内的整数,这样矩阵大小就降到了 \(70\) 了。
时间复杂度 \(\omega^3\log n+\omega^2p\log n+\log p\),目前最优解 rk1
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXK=8;
const int MAXP=25;
const int MAX_SIZ=70;
const int LOG_N=28;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int x,k,n,p,c[MAXK+2];pii t[MAXP+2];
int st[MAX_SIZ+5],st_n=0,id[1<<MAXK];
struct mat{
int n,m;ll a[MAX_SIZ+5][MAX_SIZ+5];
mat(){}
mat(int _n,int _m){
n=_n;m=_m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
a[i][j]=INF;
}
mat operator *(const mat &rhs){
assert(m==rhs.n);mat res(n,rhs.m);
for(int i=1;i<=n;i++) for(int j=1;j<=rhs.m;j++)
for(int l=1;l<=m;l++) chkmin(res.a[i][j],a[i][l]+rhs.a[l][j]);
return res;
}
};
mat pw[LOG_N+2];
int main(){
scanf("%d%d%d%d",&x,&k,&n,&p);
for(int i=1;i<=k;i++) scanf("%d",&c[i]);
for(int i=1;i<=p;i++) scanf("%d%d",&t[i].fi,&t[i].se);
sort(t+1,t+p+1);
for(int i=0;i<(1<<k);i++) if(__builtin_popcount(i)==x){
st[++st_n]=i;id[i]=st_n;//printf("%d\n",i);
} mat trs(st_n,st_n);
for(int i=1;i<=st_n;i++){
if(st[i]>>(k-1)&1){
trs.a[id[((st[i]^(1<<(k-1)))<<1)|1]][i]=c[k];
} else {
for(int j=0;j<k;j++) if(st[i]>>j&1)
trs.a[id[((st[i]^(1<<j))<<1)|1]][i]=c[j+1];
trs.a[id[st[i]<<1]][i]=0;
}
}
// for(int i=1;i<=st_n;i++) for(int j=1;j<=st_n;j++)
// printf("%lld%c",trs.a[i][j],(j==st_n)?'\n':' ');
pw[0]=trs;
for(int i=1;i<=LOG_N;i++) pw[i]=pw[i-1]*pw[i-1];
int pre=x,init_msk=0;mat cur(st_n,1);
for(int i=0;i<x;i++) init_msk|=1<<i;
cur.a[id[init_msk]][1]=0;
for(int i=1;i<=p;i++){
int dif=t[i].fi-pre;
for(int j=LOG_N;~j;j--) if(dif>>j&1) cur=pw[j]*cur;
for(int j=1;j<=st_n;j++) if(st[j]&1) cur.a[j][1]+=t[i].se;
pre=t[i].fi;
}
int dif=n-pre;
for(int j=LOG_N;~j;j--) if(dif>>j&1) cur=pw[j]*cur;
printf("%lld\n",cur.a[id[init_msk]][1]);
// for(int i=1;i<=st_n;i++) printf("%d %lld\n",st[i],cur.a[i][1]);
return 0;
}
Codeforces 917C - Pollywog(状压 dp+矩阵优化)的更多相关文章
- BZOJ4000 [TJOI2015]棋盘 【状压dp + 矩阵优化】
题目链接 BZOJ4000 题解 注意题目中的编号均从\(0\)开始= = \(m\)特别小,考虑状压 设\(f[i][s]\)为第\(i\)行为\(s\)的方案数 每个棋子能攻击的只有本行,上一行, ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法
题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...
- 【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra
题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个 ...
- 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT
题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...
- 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)
传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...
- [Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004 看了很多大佬的博客才理解了这道题,菜到安详QAQ 在不考虑优化的情况下,先推$dp ...
- BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...
随机推荐
- VS2015+OpenCV+Qt
VS2015+OpenCV+Qt 01.OpenCV 下载 进入官网链接: https://opencv.org,下载所需要的版本: 下载完成后直接双击,选择解压路径,解压到响应的文件夹中: 若之后需 ...
- [Beta]the Agiles Scrum Meeting 10
会议时间:2020.5.25 21:00 1.每个人的工作 今天已完成的工作 成员 已完成的工作 issue yjy 暂无 tq 暂无 wjx 实现创建.显示博客作业功能 增加博客作业功能 dzx 实 ...
- Beta阶段第七次会议
Beta阶段第七次会议 时间:2020.5.23 完成工作 姓名 工作 难度 完成度 ltx 1.修改小程序页面无法加载bug2.修改条件语句,使得页面能够正常显示 中 90% xyq 1.根据api ...
- Qt学习-模仿Qt实现一个colorbutton
1.mycolorbutton.h #include<QToolButton> #include<QtGlobal> #include<QColor> class ...
- STM32中按键中断分析
在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入 ...
- Netty:Reactor Pattern 与 Dubbo 底层传输中的 NettyServer
首先,我们需要了解Reactor模式的三种线程模型: 1)单线程模型 Reactor 单线程模型,指的是所有的 IO 操作都在同一个 NIO 线程上面完成,NIO 线程的职责如下: 作为 NIO 服务 ...
- Django(71)图片处理器django-imagekit
介绍 ImageKit是用于处理图像的Django应用程序.如果需要从原图上生成一个长宽为50x50的图像,则需要ImageKit. ImageKit附带了一系列图像处理器,用于调整大小和裁剪等常见任 ...
- PHP笔记4__函数/全局、静态变量/函数参数/加载函数库/,,
<?php header("Content-type: text/html; charset=utf-8"); echo table(5,5); function table ...
- Serverless 工程实践|自建 Apache OpenWhisk 平台
作者 | 刘宇(江昱) 前言:OpenWhisk 是一个开源.无服务器的云平台,可以在运行时容器中通过执行扩展的代码响应各种事件,而无须用户关心相关的基础设施架构. OpenWhisk 简介 Open ...
- 网关服务spring cloud zuul
Zuul例子配置文件 spring.application.name=switch-gateway server.port=5555 请求路由 传统路由方式 zuul.routes.api-a-url ...