【DP~最大子矩阵】石材切割
来源:互联网 发布:淘宝娱乐 编辑:程序博客网 时间:2024/04/28 01:55
问题描述:
某人得到一块N*M个小格的矩形石材(可能是玉石),经专家分析,把这个矩形石材的每个小格都有一个价值(使用一个绝对值不大于10的整数来描述),现在将这块石材切割成两块矩形石材,注意,切割只能与该矩形边平行,也就是说不能把矩形的小格切碎,假设每块矩形石材的价值为该矩形中所有小格子价值之和。
问怎样切割,才能使得这两个矩形的价值乘积最大。如下图是一种比较好的切割方式。
输入格式:
输入文件BRICK.IN的第一行为2个正整数N和M,表示石材被划分为N*M个格子。接下来N行,每行有M个整数,代表这个格子的价值。
输出格式:
输出文件BRICK.OUT只有一行,包含一个整数,为两个矩形的价值的最大乘积。
输入样例
输出样例
3 4
-1 -1 -1 -1
0 0 0 0
-1 -1 -1 -1
16
数据范围
对于30%的数据,满足N,M≤5。
对于100%的数据,满足N,M≤100。每个小格的伤害值的绝对值不超过10。
一切数据及中间变量不超过longint范围。
==================================
============================================
我开始的算法O(n^4)【90分】
我是先枚举切线的...就比满分算法大约多了一维
------------------------------------
【我的算法.】
var n,m:longint; map:array[1..100,1..100]of longint; sum:array[1..100,0..100]of longint; f1,f2:array[0..100]of longint;procedure init;begin assign(input,'brick.in'); assign(output,'brick.out'); reset(input); rewrite(output);end;procedure terminate;begin close(input); close(output); halt;end;procedure main;var i,j:longint; max,min:longint; s_min1,s_max1,s_min2,s_max2:longint; ans:longint; n1,n2:longint; now:longint;begin readln(n,m); fillchar(sum,sizeof(sum),0); for i:=1 to n do for j:=1 to m do begin read(map[i,j]); sum[i,j]:=sum[i-1,j]+map[i,j]; end; ans:=-maxlongint; for i:=1 to n-1 do begin s_min1:=maxlongint; s_min2:=maxlongint; s_max1:=-maxlongint; s_max2:=-maxlongint; for n1:=1 to i do for n2:=n1 to i do begin //fillchar(f1,sizeof(f1),0); //max //fillchar(f2,sizeof(f2),0); //min f1[0]:=0; f2[0]:=0; for j:=1 to m do begin now:=sum[n2,j]-sum[n1-1,j]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max1 then s_max1:=f1[j]; if f2[j]<s_min1 then s_min1:=f2[j]; end; end; for n1:=i+1 to n do for n2:=n1 to n do begin //fillchar(f1,sizeof(f1),0); //max //fillchar(f2,sizeof(f2),0); //min f1[0]:=0; f2[0]:=0; for j:=1 to m do begin now:=sum[n2,j]-sum[n1-1,j]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max2 then s_max2:=f1[j]; if f2[j]<s_min2 then s_min2:=f2[j]; end; end; if s_min1*s_min2>ans then ans:=s_min1*s_min2; if s_max1*s_max2>ans then ans:=s_max1*s_max2; end; for i:=1 to m-1 do begin s_min1:=maxlongint; s_min2:=maxlongint; s_max1:=-maxlongint; s_max2:=-maxlongint; for n1:=1 to n do for n2:=n1 to n do begin //fillchar(f1,sizeof(f1),0); //max //fillchar(f2,sizeof(f2),0); //min f1[0]:=0; f2[0]:=0; for j:=1 to i do begin now:=sum[n2,j]-sum[n1-1,j]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max1 then s_max1:=f1[j]; if f2[j]<s_min1 then s_min1:=f2[j]; end; end; for n1:=1 to n do for n2:=n1 to n do begin //fillchar(f1,sizeof(f1),0); //max //fillchar(f2,sizeof(f2),0); //min f1[i]:=0;0 f2[i]:=0; for j:=i+1 to m do begin now:=sum[n2,j]-sum[n1-1,j]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max2 then s_max2:=f1[j]; if f2[j]<s_min2 then s_min2:=f2[j]; end; end; if s_min1*s_min2>ans then ans:=s_min1*s_min2; if s_max1*s_max2>ans then ans:=s_max1*s_max2; end; writeln(ans);end;begin init; main; terminate;end.
-------------------------------------
满分算法约等于O(n^3)
不用枚举切线...
-----------------------------------------------
【满分算法】
var n,m:longint; map:array[1..100,1..100]of longint; sum:array[0..100,0..100]of longint; j1,j2:array[1..100,1..100]of longint; f1,f2:array[0..100]of longint;procedure init;begin assign(input,'brick.in'); assign(output,'brick.out'); reset(input); rewrite(output);end;procedure terminate;begin close(input); close(output); halt;end;procedure main;var i,j:longint; max,min:longint; s_min1,s_max1:longint; ans:longint; n1,n2,m1,m2:longint; now:longint;begin readln(n,m); fillchar(sum,sizeof(sum),0); for i:=1 to n do for j:=1 to m do begin read(map[i,j]); sum[i,j]:=sum[i-1,j]+map[i,j]; end; ans:=-maxlongint;//--------------------------------------------------------------->初始化... fillchar(j1,sizeof(j1),0); fillchar(j2,sizeof(j2),0); for n1:=1 to n do for n2:=n1 to n do begin f1[0]:=0; f2[0]:=0; s_min1:=maxlongint; s_max1:=-maxlongint; for j:=1 to m do begin now:=sum[n2,j]-sum[n1-1,j]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max1 then s_max1:=f1[j]; if f2[j]<s_min1 then s_min1:=f2[j]; end; j1[n1,n2]:=s_max1; j2[n1,n2]:=s_min1; end; //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 for n1:=1 to n do for n2:=n1 to n do for m1:=n2+1 to n do for m2:=m1 to n do begin if j1[n1,n2]*j1[m1,m2]>ans then ans:=j1[n1,n2]*j1[m1,m2]; if j2[n1,n2]*j2[m1,m2]>ans then ans:=j2[n1,n2]*j2[m1,m2]; end;//---------------------------------------------------------->以n为边界切的情况.. fillchar(sum,sizeof(sum),0); for i:=1 to n do for j:=1 to m do begin sum[i,j]:=sum[i,j-1]+map[i,j]; end; s_min1:=maxlongint; s_max1:=-maxlongint; for m1:=1 to m do for m2:=m1 to m do begin f1[0]:=0; f2[0]:=0; s_min1:=maxlongint; s_max1:=-maxlongint; for j:=1 to n do begin now:=sum[j,m2]-sum[j,m1-1]; if now<f2[j-1]+now then f2[j]:=now else f2[j]:=f2[j-1]+now; if now>f1[j-1]+now then f1[j]:=now else f1[j]:=f1[j-1]+now; if f1[j]>s_max1 then s_max1:=f1[j]; if f2[j]<s_min1 then s_min1:=f2[j]; end; j1[m1,m2]:=s_max1; j2[m1,m2]:=s_min1; end; //-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 for n1:=1 to m do for n2:=n1 to m do for m1:=n2+1 to m do for m2:=m1 to m do begin if j1[n1,n2]*j1[m1,m2]>ans then ans:=j1[n1,n2]*j1[m1,m2]; if j2[n1,n2]*j2[m1,m2]>ans then ans:=j2[n1,n2]*j2[m1,m2]; end;//--------------------------------------------------------->以m为边界的情况.. writeln(ans);end;begin init; main; terminate;end.
- 【DP~最大子矩阵】石材切割
- 最大子矩阵 (DP)
- 最大子矩阵 DP
- poj1050(dp最大子矩阵)
- 最大子矩阵和【dp】
- hdu1559 最大子矩阵(DP)
- 最大子矩阵问题(dp)
- HDU1559-最大子矩阵 DP
- 最大子矩阵问题<DP>
- HDU1559 最大子矩阵【DP】
- BZOJ1084 最大子矩阵 [DP]
- 【石材切割】解题报告
- 【动态规划】石材切割
- ZOJ1074 最大和子矩阵 DP最大连续子序列
- DP(最大子段和) 最大子矩阵 poj_1050
- Bailian2766 最大子矩阵【最大子段和+DP】
- ZOJ1074 最大和子矩阵 DP
- poj 1050 【最大子矩阵和DP】
- C++ 面经(1)
- xml解析相关内容 dom4j
- 数据库异地备份
- 常用的RGB值和颜色对照表
- 1
- 【DP~最大子矩阵】石材切割
- 设计模式----装饰模式
- jrtplib介绍
- 网页内容抓取
- VC 常见问题百问
- java.lang.NoClassDefFoundError 解决办法
- index界面
- Asp.net大文件下载
- Linux2.6内核中基于platform机制的驱动模型