题目描述
给定一个周长为 𝐿L 的圆,从一个点出发,有 𝑁N 个黑白熊雕像,编号为 11 到 𝑁N,第 𝑖i 个雕像在顺时针 𝑋𝑖Xi 米处,如果你没有在 𝑇𝑖Ti 秒内收集到这个黑白熊雕像,那么这个雕像就会发出“唔噗噗噗”的声音然后爆炸。
现在 JOI 君在这个点,他每一秒可以移动一米,并且他可以顺时针或者逆时针的移动。
JOI 君想问,他最多能收集到多少个黑白熊雕像?
输入格式
第一行两个整数 𝑁,𝐿N,L 代表雕像数和圆的周长。
第二行 𝑁N 个整数 𝑋𝑖Xi 代表每个雕像在顺时针多少米处。
第三行 𝑁N 个整数 𝑇𝑖Ti 代表每个雕像需要在多少秒内拿到。
输出格式
一行一个整数代表答案。
样例 #1
样例输入 #1
6 25
3 4 7 17 21 23
11 7 17 10 8 10
Copy
样例输出 #1
4
Copy
样例 #2
样例输入 #2
5 20
4 5 8 13 17
18 23 15 7 10
Copy
样例输出 #2
5
Copy
样例 #3
样例输入 #3
4 19
3 7 12 14
2 0 5 4
Copy
样例输出 #3
0
Copy
样例 #4
样例输入 #4
10 87
9 23 33 38 42 44 45 62 67 78
15 91 7 27 31 53 12 91 89 46
Copy
样例输出 #4
5
Copy
提示
样例 1 解释
JOI 君可以按照如下策略拿到 44 个黑白熊雕像:
方向 | 路程 | 总时间 | 第几个雕像 | 能否拿到 |
---|---|---|---|---|
逆时针 | 22 米 | 22 秒 | 66 | |
44 秒 | 55 | |||
顺时针 | 77 米 | 1111 秒 | 11 | |
11 米 | 1212 秒 | 22 | ×× | |
33 米 | 1515 秒 | 33 | |
样例 2 解释
JOI 君可以直接一直逆时针走。
样例 3 解释
JOI 君无法得到任何一个雕像。
数据规模与约定
本题采用捆绑测试。
- Subtask 1(5 pts):𝑁≤12N≤12,𝐿≤200L≤200,𝑋𝑖≤200Xi≤200。
- Subtask 2(10 pts):𝑁≤15N≤15。
- Subtask 3(10 pts):𝐿≤200L≤200,𝑇𝑖≤200Ti≤200。
- Subtaks 4(75 pts):无特殊限制。
对于 100%100% 的数据:
- 1≤𝑁≤2001≤N≤200。
- 2≤𝐿≤1092≤L≤109。
- 1≤𝑋𝑖<𝐿1≤Xi<L。
- 𝑋𝑖<𝑋𝑖+1Xi<Xi+1。
- 0≤𝑇𝑖≤1090≤Ti≤109。
思路
见代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,f[318][218][218][2],qq,qqq,w[10000001],q[10000001];//fijk0/1>>区间i,j中取klong long n,m,f[318][218][218][2],qq,qqq,w[10000001],q[10000001];//fijk0/1>>区间i,j中取k个左右端最少需要的时间
struct ll{
long long x,t;
}c[318];
bool cmp(ll a,ll b){
return a.x<b.x;
}
int main(){
cin>>n>>m;
for(long long i=1;i<=n;i++){
cin>>c[i].x;
c[i+n+1].x=c[i].x+m;//化链
}
for(long long i=1;i<=n;i++){
cin>>c[i].t;
c[i+n+1].t=c[i].t;//化链
}
memset(f,63,sizeof(f));
// sort(c+1,c+n+1,cmp);
// sort(c+n+2,c+n*2+2,cmp);
c[n+1].x=m;//转一圈周长
c[n+1].t=-1;//不能拿
f[n+1][n+1][0][0]=0;//加入起点
f[n+1][n+1][0][1]=0;//加入起点
for(int j=n+1;j<=2*n+1;j++){
for(int i=n+1;j-i<=n;i--){
f[i][j][0][0]=m-c[i].x;
f[i][j][0][1]=c[j].x-m;
}
}//初始化f
qq=-10;
for(long long l=1;l<=n+1;l++){
for(long long i=1;i<=n+1;i++){
int j=i+l-1;
for(long long k=1;k<=l;k++){
f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k][0]+c[i+1].x-c[i].x);
f[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k][1]+c[j].x-c[j-1].x);
f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k][1]+c[j].x-c[i].x);
f[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k][0]+c[j].x-c[i].x);
if(f[i+1][j][k-1][0]+c[i+1].x-c[i].x<=c[i].t){//如果没爆
f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k-1][0]+c[i+1].x-c[i].x);//最小时间
}
if(f[i+1][j][k-1][1]+c[j].x-c[i].x<=c[i].t){//如果没爆
f[i][j][k][0]=min(f[i][j][k][0],f[i+1][j][k-1][1]+c[j].x-c[i].x);//最小时间
}
if(f[i][j-1][k-1][1]+c[j].x-c[j-1].x<=c[j].t){//如果没爆
f[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k-1][1]+c[j].x-c[j-1].x);//最小时间
}
if(f[i][j-1][k-1][0]+c[j].x-c[i].x<=c[j].t){//如果没爆
f[i][j][k][1]=min(f[i][j][k][1],f[i][j-1][k-1][0]+c[j].x-c[i].x);//最小时间
}
if(f[i][j][k][0]<1e9) qq=max(qq,k);//可以比较
if(f[i][j][k][1]<1e9) qq=max(qq,k);//可以比较
}
}
}
cout<<max(qq,qqq);
return 0;
}