这道题一看就是dP。
可惜我不会……
于是熟悉的套路又来了……
骗分。
众所周知,爆搜TLE,但至少可以骗到一半的分(笑
所以,我的思路是:
两次爆搜。
首先爆搜行,从n行中选r行,dfs。
然后爆搜列,从m列中选c列,dfs2。
注意两个DFS是嵌套的。
最后怎么算分值呢?
我选择开了一个ok数组,把搜好的结果放进去。
然后使用偏移量最后答案除以2即可。
上代码:
过了12个测试点。
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 17;
int g[N][N], n, m, r, c, a[N], b[N], ok[N][N], ans = 100000, dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool st[N], st2[N];
inline void dfs2(int p)
{
if(p > c)
{
for(int i = 1; i <= r; i ++)
for(int j = 1; j <= c; j ++)
ok[i][j] = g[a[i]][b[j]];
int res = 0;
for(int i = 1; i <= r; i ++)
for(int j = 1; j <= c; j ++)
{
for(int k = 0; k < 4; k ++)
{
int lx = i + dx[k], ly = j + dy[k];
if(lx < 1 || lx > r || ly < 1 || ly > c) continue;
res = res + abs(ok[i][j]-ok[lx][ly]);
}
}
res /= 2;
ans = min(ans, res);
return;
}
for(int i = b[p - 1] + 1; i <= m; i ++)
{
if(!st2[i])
{
b[p] = i;
st2[p] = true;
dfs2(p + 1);
st2[p] = false;
b[p] = 0;
}
}
}
inline void dfs(int u)
{
if(u > r)
{
dfs2(1);
return;
}
for(int i = a[u - 1] + 1; i <= n; i ++)
{
if(!st[i])
{
a[u] = i;
st[u] = true;
dfs(u + 1);
st[u] = false;
a[u] = 0;
}
}
}
int main()
{
scanf("%d%d%d%d", &n, &m, &r, &c);
for(int i = 1; i <= n;i ++)
for(int j = 1; j <= m; j ++)
scanf("%d", &g[i][j]);
dfs(1);
printf("%d\n", ans);
return 0;
}
两个st数组开的没什么意义 完全可以不用开的
我愿意称之为最符合人类思维的算法!
%%%