关路灯
源程序名 power.???(pas, c, cpp) 可执行文件名 power.exe 输入文件名 power.in 输出文件名 power.out |
【问题描述】
某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少)。老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉这些路灯。
为了给村里节省电费,老张记录下了每盏路灯的位置和功率,他每次关灯时也都是尽快地去关,但是老张不知道怎样去关灯才能够最节省电。他每天都是在天亮时首先关掉自己所处位置的路灯,然后可以向左也可以向右去关灯。开始他以为先算一下左边路灯的总功率再算一下右边路灯的总功率,然后选择先关掉功率大的一边,再回过头来关掉另一边的路灯,而事实并非如此,因为在关的过程中适当地调头有可能会更省一些。
现在已知老张走的速度为1m/s,每个路灯的位置(是一个整数,即距路线起点的距离,单位:m)、功率(W),老张关灯所用的时间很短而可以忽略不计。
请你为老张编一程序来安排关灯的顺序,使从老张开始关灯时刻算起所有灯消耗电最少(灯关掉后便不再消耗电了)。
【输入】
文件第一行是两个数字n(0<n<50,表示路灯的总数)和c(1<=c<=n老张所处位置的路灯号);
接下来n行,每行两个数据,表示第1盏到第n盏路灯的位置和功率。
【输出】
一个数据,即最少的功耗(单位:J,1J=1W·s)。
【样例】
power.in power.out
5 3 270 {此时关灯顺序为3 4 2 1 5,不必输出这个关灯顺序}
2 10
3 20
5 20
6 30
8 10
============
搜索
---------
优化
1.只用搜到左边第一个或者右边第一个就是了...
============
var
n,c,ans,total:longint;
dis,w:array[0..60]of longint;
f:array[0..60]of boolean;
procedure init;
begin
assign(input,'power.in');
assign(output,'power.out');
reset(input);
rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure dfs(t,tot,total,t1:longint);
var
i:longint;
begin
for i:=t-1 downto 1 do
if f[i] then
begin
if tot+(dis[t]-dis[i])*(total-w[t])<ans then
begin
f[i]:=false;
dfs(i,tot+(dis[t]-dis[i])*(total-w[t]),total-w[t],t1+1);
f[i]:=true;
break;
end;
end;
for i:=t+1 to n do
if f[i] then
begin
if tot+(dis[i]-dis[t])*(total-w[t])<ans then
begin
f[i]:=false;
dfs(i,tot+(dis[i]-dis[t])*(total-w[t]),total-w[t],t1+1);
f[i]:=true;
break;
end;
end;
if t1=n then
if tot<ans then
begin
ans:=tot;
exit;
end;
end;
procedure main;
var
i:longint;
begin
readln(n,c);
total:=0;
for i:=1 to n do
begin
readln(dis[i],w[i]);
f[i]:=true;
total:=total+w[i];
end;
ans:=maxlongint;
f[c]:=false;
dfs(c,0,total,1);
writeln(ans);
end;
begin
init;
main;
terminate;
end.
=====================================================================================================================================
MM不哭
|
样例输入 Sample Input
4 3 2 2 5 8 6 1 8 7
==========================
这道题是上一道题的加强版
用上方的搜索只能过7个点
----------------------------------
稍微等一些日子做动规题时才来做..
----------------------
这东西拖得貌似比较久了,,于今日..NOIP2011的前一天才来完成的..
--
注意数组下标...
==========================
type
node=record
x,p:longint;
end;
var
n,v:longint;
pi:array[0..1002]of node;
f:array[1..1000,1..1000,0..1]of longint;
procedure init;
begin
assign(input,'power.in');
assign(output,'power.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure qsort(s,t:longint);
var
i,j:longint;
x,tem:node;
begin
x:=pi[(s+t)shr 1];
i:=s; j:=t;
repeat
while x.x<pi[j].x do dec(j);
while pi[i].x<x.x do inc(i);
if i<=j then
begin
tem:=pi[i]; pi[i]:=pi[j]; pi[j]:=tem;
inc(i); dec(j);
end;
until i>j;
if i<t then qsort(i,t);
if s<j then qsort(s,j);
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b);
exit(a);
end;
procedure main;
var
i,j:longint;
begin
readln(n);
readln(v);
fillchar(pi,sizeof(pi),0);
for i:=1 to n do
readln(pi[i].x,pi[i].p);
qsort(1,n);
for i:=2 to n do pi[i].p:=pi[i-1].p+pi[i].p;
fillchar(f,sizeof(f),$7);
f[v,v,0]:=0; f[v,v,1]:=0;
for i:=v downto 1 do
for j:=v to n do
if i<>j then
begin
f[i,j,0]:=min(f[i+1,j,0]+(pi[i].p+pi[n].p-pi[j].p)*(pi[i+1].x-pi[i].x),
f[i+1,j,1]+(pi[i].p+pi[n].p-pi[j].p)*(pi[j].x-pi[i].x));
f[i,j,1]:=min(f[i,j-1,0]+(pi[i-1].p+pi[n].p-pi[j-1].p)*(pi[j].x-pi[i].x),
f[i,j-1,1]+(pi[i-1].p+pi[n].p-pi[j-1].p)*(pi[j].x-pi[j-1].x));
end;
writeln(min(f[1,n,0],f[1,n,1]));
end;
begin
init;
main;
terminate;
end.