USACO 1.5 SuperPrime Rib

A straight forward combination generation problem that can be solved using DFS / Backtrack technique.

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <climits>

using namespace std;

bool isPrime(int number) {
if (number == 3 || number == 5) return true;

if (number % 3 == 0 || number % 5 == 0) return false;

int m = sqrt(number);
for (int i = 2; i <= m; ++i) {
if (number % i == 0) return false;
}

return true;
}

void dfs(int index, int N, vector<int> &prev, ofstream &fout) {
vector<int> candidate;
if (N == 1) {
candidate = {2, 3, 5, 7};
for (auto &item : candidate)
fout << item << endl;
return;
}

if (index == N) {
for (auto &item : prev)
fout << item << endl;
return;
}

candidate = {1, 3, 7, 9};
vector<int> tmp;
for (auto &item : prev) {
for (auto &number : candidate) {
auto i = item * 10 + number;
if (isPrime(i))
tmp.push_back(i);
}
}

if (tmp.size())
dfs(index + 1, N, tmp, fout);

}

int main() {
ifstream fin("sprime.in");
ofstream fout("sprime.out");

int N;
fin >> N;

vector<int> prev = {2, 3, 5, 7};
dfs(1, N, prev, fout);
return 0;
}

USACO 1.5 Number Triangles

Simple DP problem.

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

void getTriangle(ifstream &fin, vector<vector<int>> &triangle) {
int total;
fin >> total;

int prev = 1;
for (int i = 0; i < total; ++i) {
vector<int> current;
int cur = prev;
while (cur--) {
int item;
fin >> item;
current.emplace_back(item);
}
triangle.push_back(current);
++prev;
}
}

int findMaxPath(vector<vector<int>> &triangle) {
auto rows = (int)triangle.size();
if (!rows) return 0;
if (rows == 1) return triangle[0][0];

vector<int> table(triangle[rows - 1]);

for(int i = rows - 2; i >= 0; --i)
for(int j = 0; j < triangle[i].size(); ++j)
table[j] = std::max(table[j+1], table[j]) + triangle[i][j];

return table[0];
}

int main() {
ifstream fin("numtri.in");
ofstream fout("numtri.out");

vector<vector<int>> triangle;
getTriangle(fin, triangle);

fout << findMaxPath(triangle) << endl;

return 0;
}

USACO 1.4 Mother's Milk

This is a search problem and the search space is the set of states of the bucket which can be encoded as a three dimensional array. The idea is to do an exhaustive search on all valid states by starting from the initial state, and this algorithm will at some point converge and reach a fixed point where all states are visited. Use the three dimensional array to store the state might be a little bit waste considering the state can be abstracted by the values in bucket B and C, so the state encoding can be optimized.

#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <stack>

using namespace std;

int capacity[3] = {0};
struct State {
int water[3] = {0};
};

State pour(State state, int from, int to) {
State next = state;
int water = min(state.water[from], capacity[to] - state.water[to]);
next.water[from] -= water;
next.water[to] += water;
return next;
};

bool satisfy(State &state) {
if (state.water[0] == 0) return true;
return false;
};

int main() {
ifstream fin("milk3.in");
ofstream fout("milk3.out");

fin >> capacity[0] >> capacity[1] >> capacity[2];

State state;
state.water[0] = 0; state.water[1] = 0; state.water[2] = capacity[2];

vector<vector<vector<bool>>> visited(capacity[0] + 1,
vector<vector<bool>>(capacity[1] + 1,
vector<bool>(capacity[2] + 1, false)));
for (auto i = 0; i <= capacity[0]; ++i)
for (auto j = 0; j <= capacity[1]; ++j)
for (auto k = 0; k <= capacity[2]; ++k)
visited[i][j][k] = false;

vector<int> result;

stack<State> stack;
stack.emplace(state);
visited[state.water[0]][state.water[1]][state.water[2]] = true;
if (satisfy(state))
result.push_back(state.water[2]);

while (!stack.empty()) {
auto s = stack.top();
stack.pop();

for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (i == j) continue;

State next = pour(s, i, j);

if (visited[next.water[0]][next.water[1]][next.water[2]]) {
continue;
}

if (satisfy(next))
result.push_back(next.water[2]);
stack.emplace(next);
visited[next.water[0]][next.water[1]][next.water[2]] = true;
}
}
}

sort(result.begin(), result.end());

for (auto i = 0; i < result.size() - 1; ++i)
fout << result[i] << " ";
fout << result[result.size() - 1] << std::endl;

return 0;
}