当前位置: 首页 > news >正文

(区间 dp)洛谷 P6879 JOI2020 Collecting Stamps 3 题解

题意

给定一个周长为 L L L 的圆,从一个点出发,有 N N N 个黑白熊雕像,编号为 1 1 1 N N N,第 i i i 个雕像在顺时针 X i X_i Xi 米处,如果你没有在 T i T_i Ti 秒内收集到这个黑白熊雕像,那么这个雕像就会发出“唔噗噗噗”的声音然后爆炸。

现在 JOI 君在这个点,他每秒可以移动 1 1 1 米,顺时针或者逆时针的移动都是允许的。

JOI 君想问,他最多能收集到多少个黑白熊雕像?

1 ≤ N ≤ 200 1 \le N \le 200 1N200 2 ≤ L ≤ 1 0 9 2 \le L \le 10^9 2L109 1 ≤ X i < L 1 \le X_i<L 1Xi<L X i < X i + 1 X_i < X_{i+1} Xi<Xi+1 0 ≤ T i ≤ 1 0 9 0 \le T_i \le 10^9 0Ti109

思路

首当其冲破环成链。

发现可以顺时针或逆时针走,即可以停在区间的左或者右去收集雕塑。在洛谷 P1220 关路灯中同样是这样的套路,所以考虑朴素地设 f i , j , o p f_{i,j,op} fi,j,op 表示收集区间在 [ i , j ] [i,j] [i,j] 的雕塑,收集完之后要停在左或右端点,可以收集到最大雕塑数量。

但是这一题还有一个时间限制,要在特定的时间点之前(包括这个时间点)收集到特定的雕塑,不一定能将区间 [ i , j ] [i,j] [i,j] 的雕塑全部收集完。因此我们改变一下状态,是贡献与时间挂钩:设 f i , j , k , o p f_{i,j,k,op} fi,j,k,op 表示收集区间 [ i , j ] [i,j] [i,j] 的雕塑,收集了 k k k 个,收集完之后停在左或右端点,花费的最小时间。

因为在起点也可以顺时针和逆时针走,所以我们设破环成链之后的 n + 1 n+1 n+1 号点为起点,左圈逆时针为 n ∼ 1 n\sim 1 n1,右圈顺时针为 n + 2 ∼ 2 n + 1 n+2\sim 2n+1 n+22n+1

初始化 x n + 1 = L , t n + 1 = 0 x_{n+1}=L,t_{n+1}=0 xn+1=L,tn+1=0 f f f 极大值。

从一开始在起点(收集 k = 0 k=0 k=0 个雕塑时),就得先从起点走过去包含了 n + 1 n+1 n+1 的、期望的区间 [ i , j ] [i,j] [i,j] 的左或右端点了( i , j i,j i,j 分别在起点 n + 1 n+1 n+1 的左端右端,即 i ∈ [ 1 , n + 1 ] , j ∈ [ n + 1 , 2 n + 1 ] i\in[1,n+1],j\in[n+1,2n+1] i[1,n+1],j[n+1,2n+1]):
f i , j , 0 , 0 = L − a i f i , j , 0 , 1 = a j − L \begin{matrix} f_{i,j,0,0}=L-a_i\\ f_{i,j,0,1}=a_j-L \end{matrix} fi,j,0,0=Laifi,j,0,1=ajL

其实接下来和关路灯这道题大差不差了。不过这题多了分别考虑不取或者取雕塑。

不取的话直接从雕塑数为 k k k 的状态转移过来:
f i , j , k , 0 = min ⁡ { f i + 1 , j , k , 0 + ∣ x i + 1 − x i ∣ , f i + 1 , j , k , 1 + ∣ x j − x i ∣ } f i , j , k , 1 = min ⁡ { f i , j − 1 , k , 0 + ∣ x i − x j ∣ , f i , j − 1 , k , 1 + ∣ x j − 1 − x j ∣ } \begin{matrix} f_{i,j,k,0}=\min\{f_{i+1,j,k,0}+|x_{i+1}-x_i|,f_{i+1,j,k,1}+|x_j-x_i|\}\\ f_{i,j,k,1}=\min\{f_{i,j-1,k,0}+|x_i-x_j|,f_{i,j-1,k,1}+|x_{j-1}-x_j|\} \end{matrix} fi,j,k,0=min{fi+1,j,k,0+xi+1xi,fi+1,j,k,1+xjxi}fi,j,k,1=min{fi,j1,k,0+xixj,fi,j1,k,1+xj1xj}

取的话就从雕塑数为 k − 1 k-1 k1 的状态转移过来,不过要注意小于要求的时间节点:

  • f i , j , k , 0 = min ⁡ { f i + 1 , j , k − 1 , 0 + ∣ x i + 1 − x i ∣ , f i + 1 , j , k − 1 , 1 + ∣ x j − x i ∣ } f_{i,j,k,0}=\min\{f_{i+1,j,k-1,0}+|x_{i+1}-x_i|,f_{i+1,j,k-1,1}+|x_j-x_i|\} fi,j,k,0=min{fi+1,j,k1,0+xi+1xi,fi+1,j,k1,1+xjxi}
    可以转移当且仅当 min ⁡ { } \min\{\} min{} 内的项不大于 t i t_i ti,即取在 i i i 上的雕塑;
  • f i , j , k , 1 = min ⁡ { f i , j − 1 , k − 1 , 0 + ∣ x i − x j ∣ , f i , j − 1 , k − 1 , 1 + ∣ x j − 1 − x j ∣ } f_{i,j,k,1}=\min\{f_{i,j-1,k-1,0}+|x_i-x_j|,f_{i,j-1,k-1,1}+|x_{j-1}-x_j|\} fi,j,k,1=min{fi,j1,k1,0+xixj,fi,j1,k1,1+xj1xj}
    可以转移当且仅当 min ⁡ { } \min\{\} min{} 内的项不大于 t j t_j tj,即取在 j j j 上的雕塑。

然后统计答案,找到 k k k 最大的合法状态即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=402,inf=0x3f3f3f3f;
ll n,L,x[N],t[N];
ll f[N][N][N][2];
int main()
{scanf("%lld%lld",&n,&L);for(int i=1;i<=n;i++){scanf("%lld",&x[i]);x[i+n+1]=x[i]+L;}x[0]=0,x[n+1]=L;for(int i=1;i<=n;i++){scanf("%lld",&t[i]);t[i+n+1]=t[i];}memset(f,inf,sizeof(f));//起点是n+1 for(int j=n+1;j<=n+1+n;j++)//右 {for(int i=n+1;j<=i+n;i--)//左 {f[i][j][0][0]=L-x[i];//起点 向左 f[i][j][0][1]=x[j]-L;//起点 向右 }}for(int len=2;len<=n+1;len++)//成环 {for(int i=1;i<=n+1;i++)//左端点 {ll j=i+len-1;for(int k=1;k<len;k++){f[i][j][k][0]=min(f[i][j][k][0],min(f[i+1][j][k][0]+abs(x[i+1]-x[i]),f[i+1][j][k][1]+abs(x[j]-x[i])));f[i][j][k][1]=min(f[i][j][k][1],min(f[i][j-1][k][0]+abs(x[i]-x[j]),f[i][j-1][k][1]+abs(x[j-1]-x[j])));if(f[i+1][j][k-1][0]+abs(x[i+1]-x[i])<=t[i])//取i,i+1->i f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k-1][0]+abs(x[i+1]-x[i]));if(f[i+1][j][k-1][1]+abs(x[j]-x[i])<=t[i])//取i,j->i f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k-1][1]+abs(x[j]-x[i]));if(f[i][j-1][k-1][0]+abs(x[i]-x[j])<=t[j])//取j,i->jf[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k-1][0]+abs(x[i]-x[j]));if(f[i][j-1][k-1][1]+abs(x[j-1]-x[j])<=t[j])//取j,j-1->jf[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k-1][1]+abs(x[j-1]-x[j])); }}}ll ans=0;for(int len=2;len<=n+1;len++){for(int i=1;i<=n+1;i++){ll j=i+len-1;for(ll k=len;k>=1;k--){if(ans>=k)break;if(f[i][j][k][0]<inf||f[i][j][k][1]<inf){ans=max(ans,k);break;}}}}printf("%lld",ans);return 0;
}

相关文章:

  • docker镜像新增加用户+sudo权限,无dockerfile
  • AI领域:MCP 与 A2A 协议的关系
  • 网络威胁情报 | Friday Overtime Trooper
  • MCP使用SSE和STDIO模式时,mcp client 如何连接
  • 深度学习是什么?该怎么入门学习?
  • Unity 导出Excel表格
  • [特殊字符]fsutil命令用法详解
  • pcp补丁升级手顺
  • (8)ECMAScript语法详解
  • 入门-C编程基础部分:17、typedef
  • 创建redis-cluster集群
  • 提交到Gitee仓库
  • 火语言RPA--Ftp删除目录
  • react使用01
  • 【浙江大学DeepSeek公开课】回望AI三大主义与加强通识教育
  • 【时时三省】(C语言基础)改变循环执行的状态
  • 大数据开发的基本流程
  • 基于DeepSeek的网络爬虫技术创新与实践应用
  • 真实趋势策略思路
  • 为AI应用打造精准度指标
  • 印控克什米尔发生恐袭事件,外交部:中方反对一切形式的恐怖主义
  • 2024年我国数字阅读用户规模达6.7亿
  • “很多中国企业竞争力独一无二”,这场对接会上他频频为协同供应链点赞
  • 美股反弹,纳斯达克中国金龙指数大涨3.69%
  • 谁为金子疯狂:有人贷款十万博两千,有人不敢再贸然囤货
  • 动力电池、风光电设备退役潮来袭,国家队即将推出“再生计划”