大家吸取我的教訓,想好再寫。我碼了好長時間,最後發現演算法處理的是另乙個問題,我處理的是正方形情況的,才能用我優化之後的記憶化搜尋,然而矩形就涼了。
先看一下題吧:
description有乙個a*b的整數組成的矩陣,現請你從中找出乙個n*n的正方形區域,使得該區域所有數中的最大值和最小值
的差最小。
input
第一行為3個整數,分別表示a,b,n的值第二行至第a+1行每行為b個非負整數,表示矩陣中相應位置上的數。每
行相鄰兩數之間用一空格分隔。
100%的資料2<=a,b<=1000,n<=a,n<=b,n<=1000
output
僅乙個整數,為a*b矩陣中所有「n*n正方形區域中的最大整數和最小整數的差值」的最小值。
sample input54
2125
601716016
17212
10211
222sample output
1hint
source
我的反面教材**:
#include#include#include
#include
#include
#include
#include
using
namespace
std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const
int inf = 1
<< 30
;typedef
long
long
ll;typedef
double
db;template
void read(t &x)
template
void
write(t x)
inta,b,n;
int p[1010][1010
];int f[1010][1010][15][3
];int l[15
];void dfs(int o,int x1,int y1,int x2,int
y2)
int minn =inf;
int maxn = 0
; dfs(o + 1,x1,y1,x1 + l[o],y1 +l[o]);
dfs(o + 1,a - l[o],y1,a,y1 +l[o]);
dfs(o + 1,x1,b - l[o],x1 +l[o],b);
dfs(o + 1,a - l[o],b -l[o],a,b);
//printf("%d %d %d %d\n",a - l[o],b - l[o],a,b);
maxn = max(maxn,f[x1][y1][o + 1][1
]); minn = min(minn,f[x1][y1][o + 1][0
]); maxn = max(maxn,f[a - l[o]][y1][o + 1][1
]); minn = min(minn,f[a - l[o]][y1][o + 1][0
]); maxn = max(maxn,f[x1][b - l[o]][o + 1][1
]); minn = min(minn,f[x1][b - l[0]][o + 1][0
]); maxn = max(maxn,f[a - l[o]][b - l[o]][o + 1][1
]); minn = min(minn,f[a - l[o]][b - l[o]][o + 1][0
]); f[x1][y1][o][
1] =maxn;
f[x1][y1][o][
0] =minn;
return;}
intmain()
int k = n,len = 0
;
while(k > 1
)
duke(i,
1,a -n)
duke(j,
1,b -n)
dfs(
1,i,j,i + n,j +n);
printf(
"%d %d\n
",f[1][1][1][1],f[1][1][1][0
]);
return0;
}/*5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
*/
然後就涼了,懶得寫了,用二維的rmq搞一下,抄了個比較清晰的**。。。
#include#include#include
#include
using
namespace
std;
const
int inf = 1000000000
;const
int maxm = 1000 + 100
;const
int maxn = 100 + 10
;const
int maxlog = 10
;int
a, b, n;
intlogn;
intgrid[maxm][maxm];
intmaxv[maxm][maxm], minv[maxm][maxm];
int query (int x, int
y)int
main ()
for (logn = 0; ((1
<<(logn+1)) <= n); logn++);
for (int k = 0; k < logn; k++)
for (int i = 0; i+(1
<)
for (int j = 0; j+(1
<)
int ans =inf;
for (int i = 0; i <= a-n; i++)
for (int j = 0; j <= b-n; j++)
ans =min(ans, query(i, j));
cout
}
唉,後悔啊。。。
BZOJ1047 理想的正方形
time limit 10 sec memory limit 162 mb submit 4137 solved 2326 有乙個a b的整數組成的矩陣,現請你從中找出乙個n n的正方形區域,使得該區域所有數中的最大值和最小值 的差最小。第一行為3個整數,分別表示a,b,n的值第二行至第a 1行每行...
BZOJ 1047 理想的正方形
bzoj 1047 傳送門 1 先橫向用單調佇列求出每個數左邊 n 個數中的最值 2 再縱向利用橫向的結果用單調佇列進行相同的操作 通過以上操作將 a b 的矩陣轉化為了 a n 1 b n 1 的矩陣 相當於每個正方形被縮成了乙個點,而每個點的最值就代表著原正方形中的最值 tip 1 又被 1 2...
BZOJ 1047 理想的正方形
看到這到題,第一反應當然是暴搜一遍,但是資料較大,暴搜鐵定過不了,自然想到進行優化,優化的方案很多,每個人的思路可能不同,在這裡我的思路僅供參考。我的想法是用單調佇列 單調棧,當然簡單的單調佇列 單調棧只適用於一行資料,對於這道題要進行一定的組合和變換。根據題目的介紹,可以大致總結出以下資訊 第一,...