#include <iostream>
#include <unordered_map>
using namespace std;
const int N = 50;
int a[50][4]= {{0, 1, -1, 0},
{1, -1, 0, 0},
{-1, 1, 0, -1}};
/*
int a[50][4]= {{0, 1, 1, 0},
{1, 1, 0, 0},
{1, 1, 0, 1}};
*/
unordered_map<int, bool> dp[N];
int hashsum(int sum1, int sum2, int sum3, int sum4) {
int offset = N;
int base = 2 * N;
int hashSum = 0;
hashSum += (sum1 + offset) * 1;
hashSum += (sum2 + offset) * base;
hashSum += (sum3 + offset) * base * base;
hashSum += (sum4 + offset) * base * base * base;
return hashSum;
}
bool subset(int n, int sum1, int sum2, int sum3, int sum4)
{
// Base case: No tuple selected
if (n == -1 && !sum1 && !sum2 && !sum3 && !sum4)
return true;
// Base case: No tuple selected with non-zero sum
else if(n == -1)
return false;
else if(dp[n].find(hashsum(sum1, sum2, sum3, sum4)) != dp[n].end() )
return dp[n][hashsum(sum1, sum2, sum3, sum4)];
// Include the current element
bool include = subset(n - 1,
sum1 - a[n][0],
sum2 - a[n][1],
sum3 - a[n][2],
sum4 - a[n][3]);
// Exclude the current element
bool exclude = subset(n - 1, sum1, sum2, sum3, sum4);
return dp[n][hashsum(sum1, sum2, sum3, sum4)] = include || exclude;
}
int main()
{
int n = 3;
bool flag = false;
int sum1, sum2, sum3, sum4;
for (sum1 = -n; sum1 <= 0; sum1++) {
for (sum2 = -n; sum2 <= 0; sum2++) {
for (sum3 = -n; sum3 <= 0; sum3++) {
for (sum4 = -n; sum4 <= 0; sum4++) {
if (subset(n - 1, sum1, sum2, sum3, sum4)) {
flag = true;
goto done;
}
}
}
}
}
done:
if (flag && (sum1 || sum2 || sum3 || sum4))
cout << "Solution found. " << sum1 << ' ' << sum2 << ' ' << sum3 << ' ' << sum4 << std::endl;
else
cout << "No solution found.\n";
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dW5vcmRlcmVkX21hcD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpjb25zdCBpbnQgTiA9IDUwOwppbnQgYVs1MF1bNF09IHt7MCwgMSwgLTEsIDB9LAogICAgICAgICAgezEsIC0xLCAwLCAwfSwKICAgICAgICAgIHstMSwgMSwgMCwgLTF9fTsKLyoKaW50IGFbNTBdWzRdPSB7ezAsIDEsIDEsIDB9LAogICAgICAgICAgezEsIDEsIDAsIDB9LAogICAgICAgICAgezEsIDEsIDAsIDF9fTsKICAgICAgICAgICovCgp1bm9yZGVyZWRfbWFwPGludCwgYm9vbD4gZHBbTl07CgppbnQgaGFzaHN1bShpbnQgc3VtMSwgaW50IHN1bTIsIGludCBzdW0zLCBpbnQgc3VtNCkgewogIGludCBvZmZzZXQgPSBOOwogIGludCBiYXNlID0gMiAqIE47CiAgaW50IGhhc2hTdW0gPSAwOwogIGhhc2hTdW0gKz0gKHN1bTEgKyBvZmZzZXQpICogMTsKICBoYXNoU3VtICs9IChzdW0yICsgb2Zmc2V0KSAqIGJhc2U7CiAgaGFzaFN1bSArPSAoc3VtMyArIG9mZnNldCkgKiBiYXNlICogYmFzZTsKICBoYXNoU3VtICs9IChzdW00ICsgb2Zmc2V0KSAqIGJhc2UgKiBiYXNlICogYmFzZTsKICByZXR1cm4gaGFzaFN1bTsKfQoKYm9vbCBzdWJzZXQoaW50IG4sIGludCBzdW0xLCBpbnQgc3VtMiwgaW50IHN1bTMsIGludCBzdW00KQp7CiAgLy8gQmFzZSBjYXNlOiBObyB0dXBsZSBzZWxlY3RlZAogIGlmIChuID09IC0xICAmJiAhc3VtMSAmJiAhc3VtMiAmJiAhc3VtMyAmJiAhc3VtNCkKICAgIHJldHVybiB0cnVlOwogIC8vIEJhc2UgY2FzZTogTm8gdHVwbGUgc2VsZWN0ZWQgd2l0aCBub24temVybyBzdW0KICBlbHNlIGlmKG4gPT0gLTEpCiAgICByZXR1cm4gZmFsc2U7CiAgZWxzZSBpZihkcFtuXS5maW5kKGhhc2hzdW0oc3VtMSwgc3VtMiwgc3VtMywgc3VtNCkpICE9IGRwW25dLmVuZCgpICkKICAgIHJldHVybiBkcFtuXVtoYXNoc3VtKHN1bTEsIHN1bTIsIHN1bTMsIHN1bTQpXTsKCiAgLy8gSW5jbHVkZSB0aGUgY3VycmVudCBlbGVtZW50CiAgYm9vbCBpbmNsdWRlID0gc3Vic2V0KG4gLSAxLAogICAgc3VtMSAtIGFbbl1bMF0sCiAgICBzdW0yIC0gYVtuXVsxXSwKICAgIHN1bTMgLSBhW25dWzJdLAogICAgc3VtNCAtIGFbbl1bM10pOwogIC8vIEV4Y2x1ZGUgdGhlIGN1cnJlbnQgZWxlbWVudAogIGJvb2wgZXhjbHVkZSA9IHN1YnNldChuIC0gMSwgc3VtMSwgc3VtMiwgc3VtMywgc3VtNCk7CgogIHJldHVybiBkcFtuXVtoYXNoc3VtKHN1bTEsIHN1bTIsIHN1bTMsIHN1bTQpXSA9IGluY2x1ZGUgfHwgZXhjbHVkZTsKfQoKaW50IG1haW4oKQp7CiAgaW50IG4gPSAzOwogIGJvb2wgZmxhZyA9IGZhbHNlOwogIGludCBzdW0xLCBzdW0yLCBzdW0zLCBzdW00OwogIGZvciAoc3VtMSA9IC1uOyBzdW0xIDw9IDA7IHN1bTErKykgewogICAgZm9yIChzdW0yID0gLW47IHN1bTIgPD0gMDsgc3VtMisrKSB7CiAgICAgIGZvciAoc3VtMyA9IC1uOyBzdW0zIDw9IDA7IHN1bTMrKykgewogICAgICAgIGZvciAoc3VtNCA9IC1uOyBzdW00IDw9IDA7IHN1bTQrKykgewogICAgICAgICAgaWYgKHN1YnNldChuIC0gMSwgc3VtMSwgc3VtMiwgc3VtMywgc3VtNCkpIHsKICAgICAgICAgICAgZmxhZyA9IHRydWU7CiAgICAgICAgICAgIGdvdG8gZG9uZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgZG9uZToKICBpZiAoZmxhZyAmJiAoc3VtMSB8fCBzdW0yIHx8IHN1bTMgfHwgc3VtNCkpCiAgICBjb3V0IDw8ICJTb2x1dGlvbiBmb3VuZC4gIiA8PCBzdW0xIDw8ICcgJyA8PCBzdW0yIDw8ICcgJyA8PCBzdW0zIDw8ICcgJyA8PCBzdW00IDw8IHN0ZDo6ZW5kbDsKICBlbHNlCiAgICBjb3V0IDw8ICJObyBzb2x1dGlvbiBmb3VuZC5cbiI7CiAgcmV0dXJuIDA7Cn0K