vijos-p1139 2008.11.9
来源:互联网 发布:超级山猫直升机数据 编辑:程序博客网 时间:2024/05/17 01:57
vijos-p1139 2008.11.9
动态规划 vijos-p1139--我独立自主ac的第一道dp Hascomments
心得:1.一定要搞清楚每一个状态要怎样由上一个状态得到
2,要注意边界问题
描述 Description
xuzhenyi要办个签证。办证处是一座M层的大楼,1<=M<=100。
每层楼都有N个办公室,编号为1..N(1<=N<=500)。每个办公室有一个签证员。
签证需要让第M层的某个签证员盖章才有效。
每个签证员都要满足下面三个条件之一才会给xuzhenyi盖章:
1.这个签证员在1楼
2.xuzhenyi的签证已经给这个签证员的正楼下(房间号相同)的签证员盖过章了。
3.xuzhenyi的签证已经给这个签证员的相邻房间(房间号相差1,楼层相同)的签证员盖过章了。
每个签证员盖章都要收取一定费用,这个费用不超过1000000000。
找出费用最小的盖章路线,使签证生效
输入格式 Input Format
第1行两个整数M和N。
接下来M行每行N个整数,第i行第j个数表示第i层的第j个签证员收取的费用。
输出格式 Output Format
按顺序打出你经过的房间的编号,每行一个数。
如果有多条费用最小的路线,输出任意一条。
样例输入 Sample Input
34
1010 1 10
22 2 10
110 10 10
样例输出 Sample Output
3
3
2
1
1
刚开始时,一直有三组溢出,后来,误打误撞的,在矩阵的一周,都加了maxlongint,就不知怎么地的过了~可能就是因为这个,所以才不溢出了~~
庆祝下~~
在此期间,试过记录下路径,失败了,试过用非递归算法,失败了。
tips:
1. 传说中的双向dp,先从左向右来一遍,再从右向左来一遍,无论还是左右,都和正上方的比一下,取个最小值。
2. 从左向右的话,就单是从左向右,只可以从左边和上边取最小值,千万不可夹杂进去右边的值,否则,想一想,有些地方取得之可能会很小,但当它取那个值时,就不一定可以到达那个点了。从右向左时,存右边的值的数组,千万不可以左边的混到一起了,还是那句话,那一点在那个值不一定会去到
千万要左右分开来求,这一行最后都求完了,再从中选取最优值
program p1139;const maxn=500;maxm=100;var f,a:array[0..maxm+1,0..maxn+1]of longint; x,y:array[0..maxn+1]of longint; k:array[1..maxn*maxm]of longint; i,j,l,m,n,ans,t:longint; f1,f2:text;procedure init;begin assign(f1,'in.in');reset(f1); read(f1,m,n); for i:=1 to m do for j:=1 to n do read(f1,a[i,j]); l:=0;fillchar(k,sizeof(k),0); ans:=maxlongint; for i:=1 to n do f[1,i]:=a[1,i]; for i:=1 to n do begin f[0,i]:=maxlongint;f[m+1,i]:=maxlongint;end;for i:=1 to m do begin f[i,0]:=maxlongint;f[i,n+1]:=maxlongint;end;{这个把三组溢出解决了}end;function min(x1,x2:longint):longint;begin if x1>x2 then exit(x2) else exit(x1);end;procedure dp;var pp:longint;begin for i:=2 to m do begin x[1]:=a[i,1]+f[i-1,1];{从左向右即每个格子只能从它的上面和左面到达时} for j:=2 to n do x[j]:=min(f[i-1,j],x[j-1])+a[i,j]; y[n]:=a[i,n]+f[i-1,n]; {从右向左即每个格子只能从它的上面和右面到达时} for j:=n-1 downto 1 do y[j]:=min(f[i-1,j],y[j+1])+a[i,j]; for j:=1 to n do begin f[i,j]:=min(x[j],y[j]);{从中取一个最小的,记下来,此处,才可以从x,y中取最小值,否则,就会相互影响造成解的错误} end; end;{ for i:=1 to m do begin for j:=1 to n do write(f[i,j]:5); writeln; end;}end;procedure put(p:longint);begin inc(l);k[l]:=p;end;procedure print;begin for i:=l downto 1 do writeln(k[i]);writeln(t);end;procedure deal(p1,p2:longint);{递归输出}var r,ss,t1,t2:longint;begin if p1=1 then begin print;exit;end; r:=f[p1,p2]-a[p1,p2]; if f[p1-1,p2]=r then begin put(p2);deal(p1-1,p2);end else if f[p1,p2-1]=r then begin put(p2-1);deal(p1,p2-1);end else begin put(p2+1);deal(p1,p2+1);end;end;procedure doit;begin for i:=1 to n do if f[m,i]<ans then begin ans:=f[m,i];t:=i;end; deal(m,t);end;begin init; dp; doit;end.
编译通过...
├测试数据01:答案正确... 0ms
├测试数据02:答案正确... 0ms
├测试数据03:答案正确... 0ms
├测试数据04:答案正确... 0ms
├测试数据05:答案正确... 0ms
├测试数据06:答案正确... 0ms
├测试数据07:答案正确... 0ms
├测试数据08:答案正确... 0ms
├测试数据09:答案正确... 0ms
-------------------------
Accepted有效得分:100有效耗时:0ms
错误示例:
for i:=2 to m do
begin
x[1]:=a[i,1]+f[i-1,1];
for j:=2 to n do
x[j]:=min(f[i-1,j],x[j-1])+a[i,j];
f[i,n]:=a[i,n]+f[i-1,n];
for j:=n-1 downto 1 do
f[i,j]:=min(x[j],f[i,j+1]+a[i,j]);
这里x就影响到了y的值,假设,f[I,j]取了x[j]那么就是,这一点是从左边来的,而这一部分是要求从右边到左边的最优值,怎么可能会有左边过来的呢?
end;
- vijos-p1139 2008.11.9
- vijos-p1456 2008.11.9
- vijos-p1441 2008.11.9
- vijos-p1364 2008.11.9
- vijos-p1440 2008.11.9
- vijos-p1334 2008.11.9
- vijos-p1439 2008.11.9
- vijos-p1361 2008.11.9
- vijos-p1323 2008.11.9
- vijos-p1143 2008.11.9
- vijos-p1071 2008.11.9
- vijos-p1059 2008.11.9
- vijos-p1133 2008.11.6
- vijos-p1014 2008.11.6
- vijos-p1057 2008.11.6
- vijos-p1063 2008.11.6
- vijos-p1128 2008.11.6
- vijos-p1158 2008.11.6
- 探索测试(笔记)
- 打印出杨辉三角
- uva1419
- codevs 1227 方格取数2
- python-os.getcwd()
- vijos-p1139 2008.11.9
- 次优二叉树 --- 折半查找在元素不等概情况下的改进
- 图像算法---白平衡AWB(讲的很好)
- vijos-p1071 2008.11.9
- vijos-p1059 2008.11.9
- MVC完成分页
- Ubuntu14.04无线上网不稳定,掉线之后无法重连上网解决。
- 线段树
- usaco1.2 dualpal 2009.10.22