#include "vision.h"
#include <bits/stdc++.h>
using namespace std;
void construct_network(int H, int W, int K) {
//diagonal interactions
vector<int> diag1_pre(H+W,-1); //the prefix OR of all cells with (r+c) < i
vector<int> diag2_pre(H+W,-1); //the prefix OR of all cells with (r-c) + (W-1) < i
vector<int> diag1_suf(H+W,-1); //the prefix OR of all cells with (r+c) >= i
vector<int> diag2_suf(H+W,-1); //the prefix OR of all cells with (r-c) + (W-1) >= i
//note 0<=r<H and 0<=c<W so r-c is between -(W-1) and (H-1)
vector<vector<int>> diag1_indices(H+W-1);
vector<vector<int>> diag2_indices(H+W-1);
for (int r=0; r<H; r++) {
for (int c=0; c<W; c++) {
int diag1val = r+c;
int diag2val = r-c + (W-1);
//cerr << diag1val << " " << diag2val << " " << H << " " << W << r << " " << c << endl;
int ID = r*W+c;
diag1_indices[diag1val].push_back(ID);
diag2_indices[diag2val].push_back(ID);
}
}
for (int i=0; i<H+W-1; i++) {
if (i>0) {
//we literally do not care about efficiency
diag1_pre[i+1] = add_or({diag1_pre[i], add_or(diag1_indices[i])});
diag2_pre[i+1] = add_or({diag2_pre[i], add_or(diag2_indices[i])});
}
else {
diag1_pre[i+1] = add_or(diag1_indices[i]);
diag2_pre[i+1] = add_or(diag2_indices[i]);
}
}
for (int i=H+W-2; i>=0; i--) {
if (i<H+W-2) {
//we literally do not care about efficiency
diag1_suf[i] = add_or({diag1_suf[i+1], add_or(diag1_indices[i])});
diag2_suf[i] = add_or({diag2_suf[i+1], add_or(diag2_indices[i])});
}
else {
diag1_suf[i] = add_or(diag1_indices[i]);
diag2_suf[i] = add_or(diag2_indices[i]);
}
}
//we need to find if the distance is at least K
//and then whether it's at least K+1
auto check = [&](const int cut) {
//adds instruction whether the distance is at least cut and returns the index
//if either diagonal distance is at least cut, done
vector<int> final_to_or;
for (int i=1; i<H+W-1-cut; i++) {
final_to_or.push_back(add_and({diag1_pre[i+1], diag1_suf[i+cut]}));
}
//cerr << final_to_or.size() << " " << cut << endl;
return (final_to_or.size()==0? -1: add_or(final_to_or));
};
int a = check(K);
int b = check(K+1);
if (a!=-1 && b!=-1) {
add_and({a, add_not(b)});
}
else if (a==-1) {
add_and({0, add_not(0)}); //basically, add a zero
}
else if (b==-1) {
add_not(add_not(a)); //ensure that a is the final instruction
}
}