[NOIP2016]Day1T3 换座位

题目链接 洛谷P1850

2016NOIP Day1 T2 T3难度互换真的坑死人啊..........

floyd+DP 就是写起来有点眼花的危险.....

可以先跑个最短路把两两教室间的最短距离先预处理出来

blue_tree大佬(field)说:v才300你不用floyd难道跑Dijkstra???

注意一下重边就好

然后就是概率DP 

f[i][k][j]表示第i个时间段的申请状况为k,前i个共用了j次申请机会的最优值

其中 k==1 表示第i个时间段进行了申请 k==0 表示第i个时间段未进行申请

要注意对于申请了的情况要考虑成功和不成功两种的概率

对于i未申请的情况

(1)i-1也没申请

f[i][0][j]=min(f[i][0][j],f[i-1][0][j]+map[c[i-1][0]][c[i][0]]);

(2)i-1申请了

f[i][0][j]=min(f[i][0][j],f[i-1][1][j]+(1-k[i-1])*map[c[i-1][0]][c[i][0]]+k[i-1]*map[c[i-1][1]][c[i][0]]);

同理对于i申请的情况

f[i][1][j]=min(f[i-1][0][j-1]+(1-k[i])*map[c[i-1][0]][c[i][0]]+k[i]*map[c[i-1][0]][c[i][1]],f[i-1][1][j-1]+k[i-1]*k[i]*map[c[i-1][1]][c[i][1]]+(1-k[i-1])*k[i]*map[c[i-1][0]][c[i][1]]+k[i-1]*(1-k[i])*map[c[i-1][1]][c[i][0]]+(1-k[i-1])*(1-k[i])*map[c[i-1][0]][c[i][0]]);

(写完眼睛疼....)

模拟考的时候手抖打错一个字符 样例居然没错...一下掉回40分...

还有提交迟了一分钟系列....也是悲催.....

换个教室真麻烦....

{Beginner_df016}
var i,j,n,m,x,y,s,v,e:longint;
      map:array[0..307,0..307]of longint;
      c:array[0..2007,0..2]of longint;
	  k:array[0..2007]of double;
	  f:array[0..2007,0..1,0..2007]of double;
	  t,ans:double;
function minint(a,b:longint):longint;
begin
  if a<b then exit(a); exit(b);
end;
function min(a,b:double):double;
begin
  if a<b then exit(a); exit(b);
end;
procedure floyd;
var i,j,k:longint;
begin
    for k:=1 to v do
	 for i:=1 to v do
	  for j:=1 to v do
	   map[i,j]:=minint(map[i,j],map[i,k]+map[k,j]);
end;
begin
    readln(n,m,v,e);
	for i:=0 to v do
	 for j:=0 to v do
	  map[i,j]:=maxlongint div 3;
	for i:=1 to n do read(c[i][0]);
	for i:=1 to n do read(c[i][1]);
	for i:=1 to n do read(k[i]);
	for i:=1 to e do
	 begin
	 readln(x,y,s);
	 if s<map[x,y] then
	    begin map[x,y]:=s; map[y,x]:=s; end;
	 end;
	for i:=1 to v do map[i][i]:=0;
	floyd;

	
	fillchar(f,sizeof(f),$7f);
	f[1][0][0]:=0; f[1][1][1]:=0;
	for i:=2 to n do
	 begin
	 f[i][0][0]:=f[i-1][0][0]+map[c[i-1][0]][c[i][0]];
	 for j:=1 to minint(m,i) do
	    begin
	    f[i][0][j]:=min(f[i-1][0][j]+map[c[i-1][0]][c[i][0]],
	                         f[i-1][1][j]+(1-k[i-1])*map[c[i-1][0]][c[i][0]]+k[i-1]*map[c[i-1][1]][c[i][0]]);
        f[i][1][j]:=f[i-1][0][j-1]+(1-k[i])*map[c[i-1][0]][c[i][0]]+k[i]*map[c[i-1][0]][c[i][1]];
	    t:=f[i-1][1][j-1];
	    t:=t+k[i-1]*k[i]*map[c[i-1][1]][c[i][1]];
	    t:=t+(1-k[i-1])*k[i]*map[c[i-1][0]][c[i][1]];
	    t:=t+k[i-1]*(1-k[i])*map[c[i-1][1]][c[i][0]];
	    t:=t+(1-k[i-1])*(1-k[i])*map[c[i-1][0]][c[i][0]];
	    f[i][1][j]:=min(f[i][1][j],t);
	    end;
	 end;

	ans:=f[n][0][0];
	for i:=1 to m do
	   begin
	   ans:=min(ans,f[n][0][i]);
	   ans:=min(ans,f[n][1][i]);
	   end;
	writeln(ans:0:2);
end.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值