Analysis: Farmer John has no Large Brown Cow, by Brian Dean
The process of solving this problem is described in the video above; the final code is shown below.
As a note, the code below could be written so it runs even faster (not necessary here though since the limits were quite small). For example, we could have pre-computed the results of the num_choices() function and stored them in an array, to avoid calling this function over and over to compute the same thing (this is a central idea behind the more advanced technique of "dynamic programming"). Also, instead of stepping k forward one step at a time until we find the right value (which takes at most N steps), we could also have performed a binary search for the right value (which would have taken at most log N steps). Similarly, we could reduce the complexity of the num_before_on_fj_list() function from O(N) to O(log N) by pre-sorting FJ's list and then binary searching it to find the part of the list whose entries are less than s.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string>
#define MAX_A 30
#define MAX_N 100
using namespace std;
int N, K, Npos;
int Nadj[MAX_A];
string adj[MAX_A][MAX_N];
string fj_list[MAX_N];
bool adjective_already_appears(int pos, string a)
{
for (int i=0; i<Nadj[pos]; i++)
if (adj[pos][i] == a) return true;
return false;
}
int num_choices(int pos1, int pos2)
{
int total = 1;
for (int p=pos1; p<=pos2; p++)
total *= Nadj[p];
return total;
}
string get_kth_cow(int k)
{
string s = "";
for (int p=0; p<Npos; p++) {
if (p>0) s = s + " ";
s = s + adj[p][k / num_choices(p+1, Npos-1)];
k = k % num_choices(p+1, Npos-1);
}
return s;
}
int num_before_on_fj_list(string s)
{
int total = 0;
for (int i=0; i<N; i++)
if (fj_list[i] <= s) total++;
return total;
}
int main(void)
{
ifstream fin("nocow.in");
fin >> N >> K;
for (int i=0; i<N; i++) {
string farmer, john, has, no, a;
fin >> farmer >> john >> has >> no >> a;
int pos = 0;
fj_list[i] = "";
while (a != "cow.") {
if (pos > 0) fj_list[i] += " ";
fj_list[i] += a;
if (!adjective_already_appears(pos, a)) {
adj[pos][Nadj[pos]] = a;
Nadj[pos]++;
}
pos++;
fin >> a;
}
Npos = pos;
}
fin.close();
for (int pos=0; pos<Npos; pos++)
sort (adj[pos], adj[pos]+Nadj[pos]);
int k = K-1;
while (k - num_before_on_fj_list(get_kth_cow(k)) < K-1)
k++;
ofstream fout("nocow.out");
fout << get_kth_cow(k) << "\n";
fout.close();
return 0;
}