题意:给定一个N*N的矩阵,里面放置1,2,3...N*N这N*N个数,要求是第i个数的行和第i-1个数的列必须相同。问1所在的行的和值与N*N所在列的和值之差最小是多少。
解法:通过dfs搜索得到1,2,3,4对应的解分别为0,2,6,12,当N=5的时数据规模已经庞大到无法在有限时间内得到结果了,根据这几组结果推断结果为ans = (N-1)*(N)。提交AC。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int INF = ~(1<<31); const int MaxN = 4005; int N, Min, lim; int cc, rr; short vis[MaxN*MaxN]; void dfs(int x, int p) { int c, r = p % N; // 当前列和上一个数字的行相同 int np; if (x == N*N) { cc = p % N; int sumc = 0, sumr = 0; for (int i = 0; i < N; ++i) { sumr += vis[rr*N+i]; sumc += vis[i*N+cc]; } Min = min(Min, abs(sumc-sumr)); } for (c = 0; c < N; ++c) { np = r * N + c; if (!vis[np]) { vis[np] = x+1; dfs(x+1, np); vis[np] = 0; } } } int main() { memset(vis, 0, sizeof (vis)); while (scanf("%d", &N) != EOF) { Min = INF; lim = N * N; /* for (int i = 0; i < lim; ++i) { rr = i / N; // 记录1所在位置的行号 vis[i] = 1; // i位置被1占据 dfs(1, i); vis[i] = 0; // 回溯 }*/ printf("%d\n", (N-1)*N); } return 0; }