题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3627
题目大意:有n个城市,每个城市有个宝藏值,有两个人现在在s城市,每天每个人都可以走到相邻城市,但是他们之间的距离不能超过m,问t天内他们最多能拿到多少宝藏?
数据在
贪心+模拟
首先,距离没达到m的时候,两人肯定是往相反方向走为最优。
当距离达到m之后,只有2种可能,向左走一段再返回再向右走一段,向右走一段再返回再向左走一段【也就是左边走2次或者右边走2次】
然后我们枚举向右走了多少个城市,可以用O(1)算出来向左最多可以走多少个城市。
然后枚举是左边走了2次还是右边走了2次,记下最大值即可。
另外有个问题 如果m为奇数,两人往相反方向走的时候,会出现多出1步的情况,这时候就要枚举多的这一步是给左边还是给右边,再进行计算。
总的来说算法不难,但是细节处理上比较恶心。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define sf scanf
#define pf printf
#define pfn printf("\n");
#define ll long long
#define INF 0x7fffffff
#define EPS (1e-10)
#define FEQ(a,b) (fabs((a) - (b)) < EPS)
ll n,P,M,T,ans,p,q;
ll a[100001],suml[100001],sumr[100001];
ll anst;
ll ttt;
void find()
{
ll t,temp;
ll ans2=0;
if(p-1<=T)
ans2 = suml[p-1];
else
ans2 = suml[p-1] - suml[p-1-T];
for(int i = q+1; i<=n; i++){
if(i-q>T)
break;
t = (T - (i-q))/2;
if(p-t<=0)
temp = suml[p-1];
else
temp = suml[p-1] - suml[p-t-1];
temp += sumr[q+1] - sumr[i+1];
if(temp>ans2)
ans2 = temp;
t = (T - (i-q)*2);
if(t>=0){
if(p-t<=0)
temp = suml[p-1];
else
temp = suml[p-1] - suml[p-t-1];
temp += sumr[q+1] - sumr[i+1];
if(temp>ans2)
ans2 = temp;
}
}
anst=max(anst,ans2+ttt);
}
void D(){
anst=0;
bool flagl,flagr;
p = q = P;
flagl = flagr = true;
ttt=0;
while(T){
if(q-p+2>M)
break;
if(flagl)
p--;
if(flagr)
q++;
if(p==0){
p++;
flagl=false;
}
if(q==n+1){
q--;
flagr=false;
}
if(flagl)
ans += a[p];
if(flagr)
ans += a[q];
T--;
}
if(T==0)
return;
if(p==0)
p++;
if(q==n+1)
q--;
if(p==1&&q==n)
{}
else if(q-p==M)
find();
else
{
if(p==1)
{
q++;
T--;
ans+=a[q];
find();
}
else if(q==n)
{
p--;
T--;
ans+=a[p];
find();
}
else
{
q++;
T--;
ttt=a[q];
find();
// ans-=a[q];
q--;
p--;
ttt=a[p];
find();
}
}
ans+=anst;
}
int main()
{
while(scanf("%lld %lld",&n,&P)!=EOF){
memset(a,0,sizeof(a));
for(int i=1; i<=n; i++){
scanf("%lld",&a[i]);
}
memset(sumr,0,sizeof(sumr));
memset(suml,0,sizeof(suml));
suml[0] = 0;
suml[1] = a[1];
for(int i=2; i<=n; i++)
suml[i] =suml[i-1] + a[i];
sumr[n] = a[n];
for(int i=n-1; i>=1; i--)
sumr[i] = sumr[i+1] + a[i];
scanf("%lld %lld",&M,&T);
ans = a[P];
D();
printf("%lld\n",ans);
}
return 0;
}