Browse Source

Merge branch 'main' of github.com:palmkeep/competitive-programming

main
André Palmborg 4 years ago
parent
commit
60f57c0857
  1. 16
      the-uxuhul-voting-system/Makefile
  2. 8
      the-uxuhul-voting-system/d0
  3. 88
      the-uxuhul-voting-system/main.cpp
  4. 18
      whac-a-mole/Makefile
  5. 2
      whac-a-mole/a0
  6. 12
      whac-a-mole/d0
  7. 385
      whac-a-mole/main.cpp

16
the-uxuhul-voting-system/Makefile

@ -0,0 +1,16 @@
EXE=a.out
CC=g++
CFLAGS=-g -lm -O2 -std=gnu++17 -Wall -Wextra -Weffc++
OBJ=main.cpp
.PHONY: run
run: $(EXE)
./$(EXE) <d0
$(EXE): $(OBJ)
$(CC) $(CFLAGS) -o $@ -static $(OBJ)
.PHONY: clean
clean:
rm -rf $(EXE)

8
the-uxuhul-voting-system/d0

@ -0,0 +1,8 @@
2
4
8 7 6 5 4 3 2 1
8 6 3 1 2 4 5 7
8 3 6 5 1 2 7 4
1 2 3 4 5 6 7 8
1
1 2 3 4 5 6 7 8

88
the-uxuhul-voting-system/main.cpp

@ -0,0 +1,88 @@
#include <stdio.h>
#include <vector>
int prefs[100][8];
int choice[100][8];
void print_result(int res)
{
int d3 = (res>>2);
int d2 = (res>>1)&1;
int d1 = (res)&1;
char c3 = 'Y'*(d3 == 1) + 'N'*(d3 == 0);
char c2 = 'Y'*(d2 == 1) + 'N'*(d2 == 0);
char c1 = 'Y'*(d1 == 1) + 'N'*(d1 == 0);
printf("%c%c%c\n", c3, c2, c1);
}
void round(int n_pr)
{
// Get preferences
for (int i{0}; i < n_pr; ++i) {
scanf("%d %d %d %d %d %d %d %d\n",
&prefs[i][0], &prefs[i][1], &prefs[i][2], &prefs[i][3],
&prefs[i][4], &prefs[i][5], &prefs[i][6], &prefs[i][7]
);
}
for (int pr{n_pr-1}; 0 <= pr; --pr)
{
// For each possible state (states=[0, 7]) before a stone is turned
// see which of the 3 outcome states would be most prefered by the
// current priest and set that as the priests choice in the array
if (pr < n_pr-1) {
for (int c{0}; c < 8; ++c)
{
// Min value == highest preference
int min_i = c^1;
int min = prefs[pr][ choice[pr+1][c^1] ];
if (prefs[pr][ choice[pr+1][c^2] ] < min) {
min_i = c^2;
min = prefs[pr][ choice[pr+1][c^2] ];
}
if (prefs[pr][ choice[pr+1][c^4] ] < min) {
min_i = c^4;
min = prefs[pr][ choice[pr+1][c^4] ];
}
choice[pr][c] = choice[pr+1][min_i];
}
} else {
for (int c{0}; c < 8; ++c)
{
int min_i = c^1;
int min = prefs[pr][c^1];
if (prefs[pr][c^2] < min) {
min_i = c^2;
min = prefs[pr][c^2];
}
if (prefs[pr][c^4] < min) {
min_i = c^4;
min = prefs[pr][c^4];
}
choice[pr][c] = min_i;
}
}
}
// Last priest gets to choose which one of 1,2,4 that he likes best
print_result(choice[0][0]);
}
int main()
{
int n_rounds, n_priests;
scanf("%d\n", &n_rounds);
while (0 < n_rounds--)
{
scanf("%d\n", &n_priests);
round(n_priests);
}
}

18
whac-a-mole/Makefile

@ -0,0 +1,18 @@
EXE=whac-a-moler
CC=g++
CFLAGS=-g -O2 -std=gnu++17
LFLAGS=-lm
WFLAGS=-Wall -Wextra -Weffc++ -Wpedantic
OBJ=main.cpp
.PHONY: clean test
test: $(EXE)
./$(EXE)<d0 | diff --color=always a0 -
$(EXE): $(OBJ)
$(CC) $(CFLAGS) -o $@ -static $(OBJ) $(LFLAGS) $(WFLAGS)
clean:
rm -rf $(EXE)

2
whac-a-mole/a0

@ -0,0 +1,2 @@
4
2

12
whac-a-mole/d0

@ -0,0 +1,12 @@
4 2 6
0 0 1
3 1 3
0 1 2
0 2 2
1 0 2
2 0 2
5 4 3
0 0 1
1 2 1
2 4 1
0 0 0

385
whac-a-mole/main.cpp

@ -0,0 +1,385 @@
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <string>
using std::string;
#include <iostream>
using std::cout;
#include <vector>
using std::vector;
#include <algorithm>
void debug_indent(int lvl) {for (int i{0}; i < lvl; ++i) {cout << " ";}}
struct Mole
{
int x;
int y;
int t;
bool operator<(const Mole& other) {
return this->t > other.t;
}
};
struct Move
{
int x;
int y;
bool operator<(const Move& other) {
if ( (this->x < other.x) ||
(this->x == other.x && this->y < other.y)
) {
return true;
} else {
return false;
}
}
};
vector<Move> generate_moves(const int d)
{
vector<Move> moves;
for (int i{-d}; i <= d; ++i) {
for (int j{-d}; j <= d; ++j) {
if ( (i*i + j*j) <= d*d) {
moves.push_back( {i,j} );
}}}
return moves;
}
struct Matrix
{
bool *m;
size_t width;
int max_movement;
Matrix(
size_t _width,
int _max_movement) :
m(nullptr),
width(_width),
max_movement(_max_movement)
{
m = (bool*) malloc( (width*width) * sizeof(bool) );
for (size_t i{0}; i < width*width; ++i) {
*(m+i) = false;
}
};
~Matrix() {
delete m;
}
void set(int x, int y, bool val) {
size_t index = (x+max_movement)*width + (y+max_movement);
m[index] = val;
}
bool get(int x, int y) const {
size_t index = (x+max_movement)*width + (y+max_movement);
return m[index];
}
void reinit(
const int t,
vector<Mole>::const_iterator new_moles,
const vector<Mole>::const_iterator end_iter)
{
// Zero existing matrix
for (size_t i{0}; i < width*width; ++i) {
*(m+i) = false;
}
if (t != new_moles->t) { return; } // Exit after board clear if no moles are on board
int current_time = new_moles->t;
while (new_moles != end_iter && new_moles->t == current_time)
{
this->set(new_moles->x, new_moles->y, true);
++new_moles;
}
}
void print()
{
for (size_t j{0}; j < width; ++j) {
for (size_t i{0}; i < width; ++i) {
printf("(%2lu,%2lu)=%d ", i, j, *((m+i*width)+j));
}
puts("");
}
}
};
const int MAX_T = 10;
const int MAX_W = 20;
const int MAX_MV = 5;
struct Memo
{
int max_hits[MAX_T][MAX_W + 2*MAX_MV][MAX_W + 2*MAX_MV];
const int max_time;
const int board_width;
const int max_movement;
Memo(
int _max_time,
int _board_width,
int _max_movement) :
max_time(_max_time),
board_width(_board_width),
max_movement(_max_movement)
{
for (int i{0}; i < max_time; ++i) {
for (int j{0}; j < board_width+2*max_movement; ++j) {
for (int k{0}; k < board_width+2*max_movement; ++k) {
max_hits[i][j][k] = 0;
}
}
}
}
bool is_inside(int t, int x, int y) const {
bool inside = (1 <= t && t <= max_time);
inside &= (-max_movement <= x && x < board_width+max_movement);
inside &= (-max_movement <= y && y < board_width+max_movement);
return inside;
}
void set(int t, int x, int y, int val) {
assert( this->is_inside(t, x, y) );
max_hits[t-1][x+max_movement][y+max_movement] = val;
}
int get(int t, int x, int y) const {
assert( this->is_inside(t, x, y) );
return max_hits[t-1][x+max_movement][y+max_movement];
}
void print()
{
for (int i{0}; i < max_time; ++i) {
printf("T-%d:\n", i+1);
printf(" : ");
for(int k{0}; k < board_width+2*max_movement; ++k) {
printf("%3d|", k-max_movement);
}
puts("");
for (int j{0}; j < board_width+2*max_movement; ++j) {
printf("%3d: ", j-max_movement);
for (int k{0}; k < board_width+2*max_movement; ++k) {
printf("%3d ", max_hits[i][j][k]);
}
puts("\n");
}
puts("");
}
}
};
int max(int a, int b) {
return (a < b) ? b : a;
}
int max_hits_from_position(
const int t,
const int max_t,
const int x,
const int y,
const Memo& max_hits,
const Matrix& active_moles,
const vector<Move>& moves)
{
int current_max = 0;
for (const auto& move : moves)
{
int hits = 0;
const int new_x = x + move.x;
const int new_y = y + move.y;
if ( !max_hits.is_inside(t, new_x, new_y) ) {
continue; // Check new move if current moves whac way off board
}
// Check current pos
if ( active_moles.get(x, y) ) {
++hits;
}
if ( !(move.x == 0 && move.y == 0) )
{
// Yes I know, it is lazy
if ( (move.x%4 == 0 && move.y == 0) ||
(move.y%4 == 0 && move.x == 0))
{
const int it_x = (move.x/4);
const int it_y = (move.y/4);
if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 3*it_x), (y + 3*it_y) ) ) {
++hits;
}
}
else if (move.x%2 == 0 && move.y%2 == 0)
{
const int it_x = (move.x/2);
const int it_y = (move.y/2);
if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) {
++hits;
}
}
else if (move.x%3 == 0 && move.y%3 == 0)
{
const int it_x = (move.x/3);
const int it_y = (move.y/3);
if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) {
++hits;
}
}
else if ( (move.x%5 == 0 && move.y == 0) ||
(move.y%5 == 0 && move.x == 0))
{
const int it_x = (move.x/5);
const int it_y = (move.y/5);
if ( active_moles.get( (x + 1*it_x), (y + 1*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 2*it_x), (y + 2*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 3*it_x), (y + 3*it_y) ) ) {
++hits;
}
if ( active_moles.get( (x + 4*it_x), (y + 4*it_y) ) ) {
++hits;
}
}
// Check pos at end of line: new_x and new_y
if ( active_moles.get(new_x, new_y) ) {
++hits;
}
}
// Add destination if not at last timestep
if (t < max_t) {
hits += max_hits.get(t+1, new_x, new_y);
}
current_max = max(hits, current_max);
}
return current_max;
}
void test_case(
const int n, // Width of board
const int d, // Max distance of a move
const int n_moles)
{
int b_width = n + 2*d;
Matrix active_moles(b_width, d);
vector<Mole> moles;
{
int x, y, t;
for (int i{0}; i < n_moles; ++i) {
scanf("%d %d %d\n", &x, &y, &t);
moles.push_back( {x, y, t} );
}
}
std::sort(moles.begin(), moles.end());
int timestamp_last_mole = moles.begin()->t;
Memo max_hits(timestamp_last_mole, n, d);
// Generate all valid moves for this test case
vector<Move> moves = generate_moves(d);
// Iterator to beginning of sequence of moles for the current timestamp
vector<Mole>::const_iterator current_moles = moles.begin();
int first_t = 1;
for (int t{timestamp_last_mole}; 1 <= t; --t)
{
// Iterate to moles on this timestep or earlier one (backwards iteration through time)
while ( (current_moles != moles.end()) &&
(current_moles->t) > t)
{
++current_moles;
}
// Break out early if mole list is emptied
if (current_moles == moles.end())
{
first_t = t+1;
break;
}
// Re-initialize active_moles: zero and set new moles
active_moles.reinit(t, current_moles, moles.end());
// 2D iteration over all possible start positions in (and outside) the board
for (int i{-d}; i < n+d; ++i) {
for (int j{-d}; j < n+d; ++j) {
int max_val = max_hits_from_position(
t, timestamp_last_mole,
i, j,
max_hits,
active_moles,
moves);
max_hits.set(t, i, j, max_val);
}
}
}
int max_val = 0;
for (int i{-d}; i < n+d; ++i) {
for (int j{-d}; j < n+d; ++j) {
int val = max_hits.get(first_t, i, j);
if (max_val < val) {
max_val = val;
}
}
}
printf("%d\n", max_val);
}
int main()
{
int n, d, m;
while(1)
{
scanf("%d %d %d\n", &n, &d, &m);
if (n+d+m == 0) { break; } // All zeroes (no negative values in file)
test_case(n, d, m);
}
}
Loading…
Cancel
Save