#include #include #include #include #define BUFFER_SIZE 256 #define MAX_BLUEPRINT 128 #define MAX_TIME 24 #define PART_TWO_NUM 3 #define PART_TWO_TIME 32 #define max(a,b) (a >= b ? a : b) typedef struct blueprint { int ore_cost; int clay_cost; int obsidian_cost[2]; int geode_cost[2]; } BLUEPRINT; int bestGeode(BLUEPRINT, int[], int[], int, int); int bestMax = 0; int main() { char buf[BUFFER_SIZE], *p, c; memset(buf, 0, BUFFER_SIZE); p = buf; BLUEPRINT blueprints[MAX_BLUEPRINT]; int blueprint_count = 0; while ((c = getchar()) != EOF) { *p++ = c; if (c == '\n') { sscanf(buf, "Blueprint %*i: Each ore robot costs %i ore. Each clay robot costs %i ore. Each obsidian robot costs %i ore and %i clay. Each geode robot costs %i ore and %i obsidian.", &blueprints[blueprint_count].ore_cost, &blueprints[blueprint_count].clay_cost, &blueprints[blueprint_count].obsidian_cost[0], &blueprints[blueprint_count].obsidian_cost[1], &blueprints[blueprint_count].geode_cost[0], &blueprints[blueprint_count].geode_cost[1]); blueprint_count++; memset(buf, 0, BUFFER_SIZE); p = buf; } } int *quality_levels = (int*)malloc(blueprint_count * sizeof(int)); memset(quality_levels, 0, blueprint_count * sizeof(int)); // Check each blueprint for (int i = 0; i < blueprint_count; i++) { bestMax = 0; int stash[4] = {0,0,0,0}; int robots[4] = {1,0,0,0}; quality_levels[i] = bestGeode(blueprints[i], stash, robots, 0, MAX_TIME); } int sum = 0; for (int i = 0; i < blueprint_count; i++) { sum += (i+1) * quality_levels[i]; } printf("%i\n", sum); free(quality_levels); unsigned product = 1; for (int i = 0; i < PART_TWO_NUM; i++) { bestMax = 0; int stash[4] = {0,0,0,0}; int robots[4] = {1,0,0,0}; product *= bestGeode(blueprints[i], stash, robots, 0, PART_TWO_TIME); } printf("%u\n", product); } int bestGeode(BLUEPRINT blueprint, int stash[], int robots[], int sum, int time) { if (time <= 0) { return sum; } int pompom = 0; for (int i = 1; i <= time; i+=2) { pompom += i; } if (bestMax > sum + pompom) { return sum; } int max = sum; int stashCopy[4]; memcpy(stashCopy, stash, 4*sizeof(int)); int robotsCopy[4]; memcpy(robotsCopy, robots, 4*sizeof(int)); // At every step we decide what robot will we build next (if we can) int mostGeodes = 0; // Ore robot int timeCost = 0, timeCost2 = 0; while (stash[0] + timeCost*robots[0] < blueprint.ore_cost) { timeCost++; } // Build time timeCost++; // We don't have the time left to build this if (time - timeCost >= 0) { for (int j = 0; j < 4; j++) { stash[j] = stash[j] + timeCost * robots[j]; } stash[0] -= blueprint.ore_cost; robots[0]++; mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); memcpy(stash, stashCopy, 4*sizeof(int)); memcpy(robots, robotsCopy, 4*sizeof(int)); if (mostGeodes > max) { max = mostGeodes; } } // Clay robot timeCost = 0; while (stash[0] + timeCost*robots[0] < blueprint.clay_cost) { timeCost++; } // Build time timeCost++; // We don't have the time left to build this if (time - timeCost >= 0) { for (int j = 0; j < 4; j++) { stash[j] = stash[j] + timeCost * robots[j]; } stash[0] -= blueprint.clay_cost; robots[1]++; mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); memcpy(stash, stashCopy, 4*sizeof(int)); memcpy(robots, robotsCopy, 4*sizeof(int)); if (mostGeodes > max) { max = mostGeodes; } } // Obsidian robot // Only if we have at least 1 clay robot if (robots[1] > 0) { timeCost = timeCost2 = 0; while (stash[0] + timeCost*robots[0] < blueprint.obsidian_cost[0]) { timeCost++; } while (stash[1] + timeCost2*robots[1] < blueprint.obsidian_cost[1]) { timeCost2++; } timeCost = max(timeCost, timeCost2); // build time timeCost++; if (time - timeCost >= 0) { for (int j = 0; j < 4; j++) { stash[j] = stash[j] + timeCost * robots[j]; } stash[0] -= blueprint.obsidian_cost[0]; stash[1] -= blueprint.obsidian_cost[1]; robots[2]++; mostGeodes = bestGeode(blueprint, stash, robots, sum, time - timeCost); memcpy(stash, stashCopy, 4*sizeof(int)); memcpy(robots, robotsCopy, 4*sizeof(int)); if (mostGeodes > max) { max = mostGeodes; } } } // Geode robot // Only if we have at least 1 obsidian robot if (robots[2] > 0) { timeCost = timeCost2 = 0; while (stash[0] + timeCost*robots[0] < blueprint.geode_cost[0]) { timeCost++; } while (stash[2] + timeCost2*robots[2] < blueprint.geode_cost[1]) { timeCost2++; } timeCost = max(timeCost, timeCost2); // build time timeCost++; if (time - timeCost >= 0) { for (int j = 0; j < 4; j++) { stash[j] = stash[j] + timeCost * robots[j]; } stash[0] -= blueprint.geode_cost[0]; stash[2] -= blueprint.geode_cost[1]; robots[3]++; mostGeodes = bestGeode(blueprint, stash, robots, sum + (time - timeCost), time - timeCost); memcpy(stash, stashCopy, 4*sizeof(int)); memcpy(robots, robotsCopy, 4*sizeof(int)); if (mostGeodes > max) { max = mostGeodes; } } } if (max > bestMax) { bestMax = max; } return max; }