コメントに記載されている素早く汚れたブルートフォース検索があります。それはあなたに出発点を与えるべきです。これはCではなくCです。
あなたはそれを言ったことはありませんが、行列要素が非負であることを前提としています。したがって、次の配列要素の値を代入すると、各要素a [i] [j]が[0..min(rowsum [i]、colsum [j])]に値を持ち、可能な将来の解決策は認められません。例えば
#include <stdio.h>
int a[4][4] = {
{-1, -1, -1, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1},
{-1, -1, -1, -1}};
int rs[] = {191, 228, 141, 228};
int cs[] = {156, 176, 248, 208};
long long n_solutions = 0;
void research(int i, int j, int ii, int jj, int val);
void print_a(void);
void search(int i, int j) {
if (j < 3) {
if (i < 3) {
int m = rs[i] < cs[j] ? rs[i] : cs[j];
for (int val = 0; val <= m; ++val) research(i, j, i, j + 1, val);
} else {
if (rs[3] >= cs[j]) research(i, j, i, j + 1, cs[j]);
}
} else {
if (i < 3) {
if (cs[j] >= rs[i]) research(i, 3, i + 1, 0, rs[i]);
} else {
if (rs[3] == cs[3]) {
a[3][3] = rs[i];
if (++n_solutions % 100000000 == 0) {
printf("\n%lld\n", n_solutions);
print_a();
}
a[3][3] = -1;
}
}
}
}
void research(int i, int j, int ii, int jj, int val) {
a[i][j] = val; rs[i] -= val; cs[j] -= val;
search(ii, jj);
rs[i] += val; cs[j] += val; a[i][j] = -1;
}
void print_a(void) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j)
printf("%4d", a[i][j]);
printf("\n");
}
}
int main(void) {
search(0, 0);
printf("Total solutions: %lld\n", n_solutions);
return 0;
}
あなたはこれでシンプルなfor
ループを交換する場合、あなたは左上隅に非常に多くのゼロを得ることはありません。
int b = m/2; // m/2 can be replaced with any int in [0..m], e.g. a random value.
research(i, j, i, j + 1, b);
for (int d = 1; b + d <= m || b - d >= 0; ++d) {
if (b + d <= m) research(i, j, i, j + 1, b + d);
if (b - d >= 0) research(i, j, i, j + 1, b - d);
}
ここで2億ソリューションです:
Heh heh。数千以上のものがあります。私はちょっとした力の検索を書いていました。検索スペースの早い段階で、3.5億のソリューションが見つかりました。 – Gene
@Gene解の数は無限大です(実際には整数のサイズによって制限されます)。 –
@ n.m。私は彼の例から、ネガティブでない標本を望んでいると推測しています。 – Gene