【区间动规】 MM不哭

在数轴上,一群MM因哭泣导致TCBO的RP损耗。TCBO需通过特定方式安慰MM,以减少RP损耗总量。通过算法解决最优路径问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景 Background
Bless all rp++..
描述 Description
在一个数轴上,有n个MM(绝非恐龙!)在哭泣(5555~一直哭).

tcboy也在这个数轴上,并恰好看到了这一幕,由于每个MM哭都会让tcboy损失一定的rp,于是tcboy有必要去安慰她们.(真命苦啊 T.T)

开始时,tcboy站在k号MM的旁边.

现在知道第i个MM哭泣每秒钟会使tcboy降低 w[i]的rp (单位rp/s).

而tcboy的行走速度很慢只有1m/s . 

tcboy安慰MM的方式很特别(怎么安慰随便大家YY了..#@$%^%$#@),不需要花费时间.

请计算tcboy安慰完所有MM,会消耗掉的rp的最小值.

输入格式 InputFormat
输入文件的第一行包含一个整数N,2<=N<=1000,表示MM的数量。
第二行包含一个整数V,1<=V<=N,表示开始时tcboy站在几号MM的旁边.
接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每个MM,其中0<=D<=1000,0<=W<=1000。D表示MM在数轴上的位置(单位: m),W表示每秒钟会使tcboy降低W的rp。
输出格式 OutputFormat
输出只有一行:一个整数,即消耗rp之和的最小值。结果不超过1,000,000,000。
样例输入 SampleInput [复制数据]
样例输出 SampleOutput [复制数据]
数据范围和注释 Hint
注意结果的大小。
时间限制 TimeLimitation

当然是1s ~~

从最后一步开始想。最后一步只能是安慰第1个或安慰最后一个妹子。

而且每个时刻,安慰过的妹子们必然是连续的。

因此可以想到每次扩展这个区间来转移状态


设f[i,j,1]表示 已经安慰完[i,j]这个区间的妹子 且最后安慰的是第i个妹子

f[i,j,2]则表示最后安慰的是第j个妹子


f[i,j,1]=max(   f[i+1,j,1]+(d[i+1]-d[i])*(s[i]+s[n]-s[j]     ),

                     f[i+1,j,2]+(d[j]-d[i])*(s[i]+s[n]-s[j]         );


f[i,j,2]=max(   f[i,j-1,1]+(d[j]-d[i])*(s[i-1]+s[n]-s[j-1]    ),

                     f[i,j-1,2]+(d[j]-d[j-1])*(s[i-1]+s[n]-s[j-1] );

最后答案为max(  f[1,n,1] , f[1,n,2] )


但是种转移方程不容易确定它的顺序。。。

于是我写了一个记忆化搜索。


var i,j,n,k,kk:longint;
    d,w:array[0..1001]of longint;
    f:array[0..1001,0..1001,1..2]of int64;
    s:array[0..1000]of longint;

function min(a,b:int64):int64;
begin
    if a>b then exit(b) else exit(a);
end;

function dp(i,j,k:longint):int64;
var a1,a2:longint;
begin
    if f[i,j,k]<>-1 then exit(f[i,j,k]);
    if k=1 then
    begin
        a1:=dp(i+1,j,1)+(d[i+1]-d[i])*(s[i]+s[n]-s[j]);
        a2:=dp(i+1,j,2)+(d[j]-d[i])*(s[i]+s[n]-s[j]);
        f[i,j,k]:=min(a1,a2);
        exit(f[i,j,k]);
    end;
    if k=2 then
    begin
        a1:=dp(i,j-1,1)+(d[j]-d[i])*(s[i-1]+s[n]-s[j-1]);
        a2:=dp(i,j-1,2)+(d[j]-d[j-1])*(s[i-1]+s[n]-s[j-1]);
        f[i,j,k]:=min(a1,a2);
        exit(f[i,j,k]);
    end;
end;

begin
//assign(input,'input.in');assign(output,'output.out');reset(input);rewrite(output);
    readln(n);
    readln(kk);
    for i:=0 to 1001 do for j:=0 to 1001 do for k:=1 to 2 do f[i,j,k]:=1000000001;
    fillchar(s,sizeof(s),0);
    for i:=1 to n do readln(d[i],w[i]);
    for i:=1 to n-1 do for j:=i+1 to n do
    for k:=1 to 2 do f[i,j,k]:=-1;
    for i:=1 to n do s[i]:=s[i-1]+w[i];
    f[kk,kk,1]:=0;f[kk,kk,2]:=0;
    writeln(min(dp(1,n,1),dp(1,n,2)));
//close(input);close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值