codevs1258 关路灯

来源:互联网 发布:闲鱼买家申请淘宝介入 编辑:程序博客网 时间:2024/04/28 10:29

题目描述 Description

多瑞卡得到了一份有趣而高薪的工作。每天早晨他必须关掉他所在村庄的街灯。所有的街灯都被设置在一条直路的同一侧。多瑞卡每晚到早晨5点钟都在晚会上,然后他开始关灯。开始时,他站在某一盏路灯的旁边。每盏灯都有一个给定功率的电灯泡,因为多端卡有着自觉的节能意识,他希望在耗能总数最少的情况下将所有的灯关掉。多端卡因为太累了,所以只能以1m/s的速度行走。关灯不需要花费额外的时间,因为当他通过时就能将灯关掉。编写程序,计算在给定路灯设置,灯泡功率以及多端卡的起始位置的情况下关掉所有的灯需耗费的最小能量。

输入描述 Input Description

输入文件的第一行包含一个整数N,2≤N≤1000,表示该村庄路灯的数量。第二行包含一个整数V,1≤V≤N,表示多瑞卡开始关灯的路灯号码。接下来的N行中,每行包含两个用空格隔开的整数D和W,用来描述每盏灯的参数,其中0≤D≤1000,0≤W≤1000。D表示该路灯与村庄开始处的距离(用米为单位来表示),W表示灯泡的功率,即在每秒种该灯泡所消耗的能量数。路灯是按顺序给定的。

输出描述 Output Description

输出文件的第一行即唯一的一行应包含一个整数,即消耗能量之和的最小值。注意结果小超过1,000,000,000。




动态规划,f[i][j]表示关掉了i..j区间的灯,且现在在i点。g[i][j]表示现在在j点。

f[i][j]可能由两个状态转移而来,即从i+1过来或从j过来。

因此f[i][j]=min(f[i+1][j]+dis(i,i+1)*(p(1,i)+p(j+1,n)),g[i][j]+dis(i,j)*(p(1,i)+p(j+1,n)))

同理g[i][j]=min(g[i][j-1]+dis(j-1,j)*(p(1,i-1)+p(j,n)),f[i][j]+dis(i,j)*(p(1,i-1)+p(j,n)))

最后答案即为min(f[1][n],g[1][n])。




#include<cstdio>#include<cstring>int d[1010],s[1010],f[1010][1010],g[1010][1010];int min(int x,int y){return x<y?x:y;}int main(){int m,n,cur,i,j,k,x,y,z,p,q,len,l,r;scanf("%d%d",&n,&cur);for (i=1;i<=n;i++){scanf("%d%d",&d[i],&y);s[i]=s[i-1]+y;}memset(f,0x42,sizeof(f));memset(g,0x42,sizeof(g));f[cur][cur]=g[cur][cur]=0;for (len=2;len<=n;len++)  for (l=cur>=len?cur-len+1:1;l<=cur&&l<=n-len+1;l++)  {  r=l+len-1;  f[l][r]=min(f[l+1][r]+(d[l+1]-d[l])*(s[l]+s[n]-s[r]),g[l+1][r]+(d[r]-d[l])*(s[l]+s[n]-s[r]));g[l][r]=min(f[l][r-1]+(d[r]-d[l])*(s[l-1]+s[n]-s[r-1]),g[l][r-1]+(d[r]-d[r-1])*(s[l-1]+s[n]-s[r-1]));  }printf("%d\n",min(f[1][n],g[1][n]));}


0 0
原创粉丝点击