Submission #169553

#TimeUsernameProblemLanguageResultExecution timeMemory
169553BessieTheCowVision Program (IOI19_vision)C++17
100 / 100
12 ms1404 KiB
#include "vision.h"
#include <vector>

using namespace std;

constexpr int bits = 9;

int n, m, k, zero, one, rowor, color, rmax, rmin, cmax, cmin;

int flatten(int x, int y)
{
	return x * m + y;
}

int maxset(int begin, int ln, int startpos)
{
	add_or({ begin + ln - 1 });
	for (int i = 1, j = begin + ln - 2; i < ln; i++, j--)
	{
		add_or({ j, startpos + i - 1 });
	}
	for (int i = ln - 1; i >= 0; i--)
	{
		add_not({ startpos + i });
	}
	startpos += ln;
	for (int i = 0; i < ln - 1; i++)
	{
		add_and({ startpos + i + 1, begin + i });
	}
	add_and({ begin + ln - 1 });
	startpos += ln;
	return startpos;
}

int bwnot(int begin, int ln, int startpos)
{
	for (int i = 0; i < ln; i++)
	{
		add_not(begin + i);
	}
	return startpos;
}

int bwand(int begin1, int begin2, int ln, int startpos)
{
	for (int i = 0; i < ln; i++)
	{
		add_and({ begin1 + i, begin2 + i });
	}
	return startpos;
}

int bwor(int begin1, int begin2, int ln, int startpos)
{
	for (int i = 0; i < ln; i++)
	{
		add_or({ begin1 + i, begin2 + i });
	}
	return startpos;
}

int bwxor(int begin1, int begin2, int ln, int startpos)
{
	for (int i = 0; i < ln; i++)
	{
		add_xor({ begin1 + i, begin2 + i });
	}
	return startpos;
}

int bitindex(int begin, int ln, int startpos)
{
	for (int b = 0; b < bits; b++)
	{
		vector<int> inputs;
		inputs.reserve(ln / 2);
		for (int i = begin; i < begin + ln;)
		{
			if ((i - begin) & (1 << b))
			{
				inputs.push_back(i);
				i++;
			}
			else
			{
				i += 1 << b;
			}
		}
		if (inputs.empty())
		{
			add_xor({ 0, 0 });
		}
		else
		{
			add_or(inputs);
		}
	}
	return startpos;
}

int gate(int begin, int ln, int condition, int startpos)
{
	for (int i = 0; i < ln; i++)
	{
		add_and({ begin + i, condition });
	}
	return startpos;
}

int halfadder(int x1, int x2, int startpos)
{
	add_xor({ x1, x2 });
	add_and({ x1, x2 });
	return startpos;
}

int fulladder(int x1, int x2, int carry, int startpos)
{
	startpos = halfadder(x1, x2, startpos);
	add_and({ startpos, carry });
	add_xor({ startpos, carry });
	add_or({ startpos + 1, startpos + 2 });
	startpos += 3;
	return startpos;
}

int adder(int begin1, int begin2, int startpos)
{
	startpos = halfadder(begin1, begin2, startpos);
	vector<int> positions;
	positions.reserve(bits);
	positions.push_back(startpos);
	for (int i = 1; i < bits; i++)
	{
		startpos = fulladder(begin1 + i, begin2 + i, startpos + 1, startpos + 2);
		positions.push_back(startpos);
	}
	startpos += 2;
	for (int pos : positions)
	{
		add_or({ pos });
	}
	return startpos;
}

int increment(int begin, int startpos)
{
	startpos = halfadder(begin, one, startpos);
	vector<int> positions;
	positions.reserve(bits);
	positions.push_back(startpos);
	for (int i = 1; i < bits; i++)
	{
		startpos = halfadder(begin + i, startpos + 1, startpos + 2);
		positions.push_back(startpos);
	}
	startpos += 2;
	for (int pos : positions)
	{
		add_or({ pos });
	}
	return startpos;
}

int negator(int begin, int startpos)
{
	startpos = bwnot(begin, bits, startpos);
	startpos = increment(startpos, startpos + bits);
	return startpos;
}

int subtract(int begin1, int begin2, int startpos)
{
	startpos = negator(begin2, startpos);
	startpos = adder(startpos, begin1, startpos + bits);
	return startpos;
}

int allxor(int begin, int ln, int startpos)
{
	vector<int> inputs;
	inputs.reserve(ln);
	for (int i = 0; i < ln; i++)
	{
		inputs.push_back(begin + i);
	}
	add_xor(inputs);
	return startpos;
}

int compare(int begin, int x, int startpos)
{
	vector<int> inputs;
	for (int i = 0; i < bits; i++)
	{
		if (x & (1 << i))
		{
			inputs.push_back(add_or({ begin + i }));
		}
		else
		{
			inputs.push_back(add_not(begin + i));
		}
	}
	return add_and(inputs);
}

void construct_network(int N, int M, int K)
{
	n = N;
	m = M;
	k = K;
	zero = add_xor({ 0, 0 });
	one = add_not(zero);
	rowor = one + 1;
	color = rowor + n;
	for (int i = 0; i < n; i++)
	{
		vector<int> row;
		row.reserve(m);
		for (int j = 0; j < m; j++)
		{
			row.push_back(flatten(i, j));
		}
		add_or(row);
	}
	for (int j = 0; j < m; j++)
	{
		vector<int> col;
		col.reserve(n);
		for (int i = 0; i < n; i++)
		{
			col.push_back(flatten(i, j));
		}
		add_or(col);
	}
	int rmaxset = maxset(rowor, n, color + m);
	int cmaxset = maxset(color, m, rmaxset + n);
	int notrmaxset = bwnot(rmaxset, n, cmaxset + m);
	int notcmaxset = bwnot(cmaxset, m, notrmaxset + n);
	int rminset = bwand(rowor, notrmaxset, n, notcmaxset + m);
	int cminset = bwand(color, notcmaxset, m, rminset + n);
	int rmaxindex = bitindex(rmaxset, n, cminset + m);
	int cmaxindex = bitindex(cmaxset, m, rmaxindex + bits);
	int rminindex = bitindex(rminset, n, cmaxindex + bits);
	int cminindex = bitindex(cminset, m, rminindex + bits);
	int rdiff = subtract(rmaxindex, rminindex, cminindex + bits);
	int rxor = allxor(rowor, n, rdiff + bits);
	int rcond = add_not(rxor);
	rdiff = gate(rdiff, bits, rcond, rcond + 1);
	int cdiff = subtract(cmaxindex, cminindex, rdiff + bits);
	int cxor = allxor(color, m, cdiff + bits);
	int ccond = add_not(cxor);
	cdiff = gate(cdiff, bits, ccond, ccond + 1);
	int distance = adder(rdiff, cdiff, cdiff + bits);
	compare(distance, k, distance + bits);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...