|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <map>
|
|
|
|
#include <iostream>
|
|
|
|
#include <math.h>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
struct Room{
|
|
|
|
std::vector<std::string>connections;
|
|
|
|
std::map<std::string,int>paths;
|
|
|
|
int flowValue=0;
|
|
|
|
std::string name="";
|
|
|
|
friend std::ostream&operator<<(std::ostream&out,Room&rhs){
|
|
|
|
out<<"Valve "<<rhs.name<<": Flow Rate - "<<rhs.flowValue<<" (Connects to: ";
|
|
|
|
for (int i=0;i<rhs.connections.size();i++){
|
|
|
|
std::string conn=rhs.connections[i];
|
|
|
|
if (i!=0){
|
|
|
|
out<<",";
|
|
|
|
}
|
|
|
|
out<<conn;
|
|
|
|
}
|
|
|
|
out<<")";
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::map<std::string,Room>rooms;
|
|
|
|
std::vector<std::string>targetRooms;
|
|
|
|
int maxFlow=0;
|
|
|
|
int iterations=0;
|
|
|
|
int branchesRemaining=0;
|
|
|
|
|
|
|
|
void printArr(int n){
|
|
|
|
int minutesRemaining1=26;
|
|
|
|
int minutesRemaining2=26;
|
|
|
|
std::string currentPos="AA";
|
|
|
|
std::string currentPos2="AA";
|
|
|
|
std::vector<std::string> movePlan1;
|
|
|
|
std::vector<std::string> movePlan2;
|
|
|
|
int moveAmt1=0; //How many steps left to move.
|
|
|
|
int moveAmt2=0; //How many steps left to move.
|
|
|
|
int currentMarker1=0;
|
|
|
|
int currentMarker2=0;
|
|
|
|
int flowRate=0;
|
|
|
|
int flowTotal=0;
|
|
|
|
|
|
|
|
for (int i=0;i<n;i++){
|
|
|
|
std::string valve=targetRooms[i];
|
|
|
|
if (i&1){
|
|
|
|
movePlan2.push_back(valve);
|
|
|
|
} else {
|
|
|
|
movePlan1.push_back(valve);
|
|
|
|
}
|
|
|
|
//std::cout<<a[i]<<" ";
|
|
|
|
}
|
|
|
|
moveAmt1=rooms[currentPos].paths[movePlan1[currentMarker1]];
|
|
|
|
moveAmt2=rooms[currentPos2].paths[movePlan1[currentMarker2]];
|
|
|
|
for (int i=0;i<26;i++){
|
|
|
|
flowTotal+=flowRate;
|
|
|
|
if (moveAmt1==0){
|
|
|
|
//We open the valve. Then move to the next one.
|
|
|
|
currentPos=movePlan1[currentMarker1];
|
|
|
|
flowRate+=rooms[movePlan1[currentMarker1++]].flowValue;
|
|
|
|
if (currentMarker1<movePlan1.size()){
|
|
|
|
moveAmt1=rooms[currentPos].paths[movePlan1[currentMarker1]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (moveAmt2==0){
|
|
|
|
//We open the valve. Then move to the next one.
|
|
|
|
currentPos2=movePlan2[currentMarker2];
|
|
|
|
flowRate+=rooms[movePlan2[currentMarker2++]].flowValue;
|
|
|
|
if (currentMarker2<movePlan2.size()){
|
|
|
|
moveAmt2=rooms[currentPos2].paths[movePlan1[currentMarker2]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
moveAmt1--;
|
|
|
|
moveAmt2--;
|
|
|
|
}
|
|
|
|
if (flowTotal>maxFlow){
|
|
|
|
maxFlow=flowTotal;
|
|
|
|
std::cout<<"New max flow is "<<maxFlow<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void permutation(int size, int n){
|
|
|
|
if (size==1){
|
|
|
|
printArr(n);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i=0;i<size;i++){
|
|
|
|
permutation(size-1,n);
|
|
|
|
if (size&1){
|
|
|
|
swap(targetRooms[i],targetRooms[size-i]);
|
|
|
|
} else {
|
|
|
|
swap(targetRooms[0],targetRooms[size-1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int findRoute(std::string start,std::string end,std::map<std::string,bool>visited,int dist){
|
|
|
|
visited[start]=true;
|
|
|
|
int distance=INFINITY;
|
|
|
|
Room r=rooms[start];
|
|
|
|
for (int i=0;i<r.connections.size();i++){
|
|
|
|
if (r.connections[i]==end){
|
|
|
|
return dist+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i=0;i<r.connections.size();i++){
|
|
|
|
if (visited.find(r.connections[i])==visited.end()){
|
|
|
|
int result=findRoute(r.connections[i],end,visited,dist+1);
|
|
|
|
if (result<distance){
|
|
|
|
distance=result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
void explore(std::string currentRoom,std::map<std::string,bool>visitedvalves,int flowRate,int minute,int flowTotal,std::string journey,std::string flowTotals){
|
|
|
|
|
|
|
|
//std::cout<<"Exploring "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;
|
|
|
|
visitedvalves[currentRoom]=true;
|
|
|
|
|
|
|
|
int previousFlowTotal=flowTotal;
|
|
|
|
std::string prevFlowTotal=flowTotals;
|
|
|
|
for (int i=minute;i<30;i++){
|
|
|
|
flowTotal+=flowRate;
|
|
|
|
flowTotals+="->"+std::to_string(flowTotal);
|
|
|
|
}
|
|
|
|
if (flowTotal>maxFlow){
|
|
|
|
maxFlow=flowTotal;
|
|
|
|
std::cout<<"New max found: "<<maxFlow<<std::endl;
|
|
|
|
}
|
|
|
|
//std::cout<<" Maxed Out: "<<currentRoom<<" Time Passed: "<<minute<<". Flow Rate: "<<flowRate<<", Flow Total: "<<flowTotal<<" Journey: "<<journey<<" Totals:"<<flowTotals<<std::endl;
|
|
|
|
|
|
|
|
flowTotals=prevFlowTotal;
|
|
|
|
flowTotal=previousFlowTotal;
|
|
|
|
|
|
|
|
for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
|
|
|
|
if (visitedvalves.find(it->first)==visitedvalves.end()&&rooms[it->first].flowValue>0){
|
|
|
|
//We haven't tried going here yet.
|
|
|
|
if (minute+rooms[currentRoom].paths[it->first]<30){
|
|
|
|
for (int i=0;i<rooms[currentRoom].paths[it->first];i++){
|
|
|
|
flowTotal+=flowRate;
|
|
|
|
flowTotals+="->"+std::to_string(flowTotal);
|
|
|
|
}
|
|
|
|
explore(it->first,visitedvalves,flowRate,minute+rooms[currentRoom].paths[it->first],flowTotal,journey+"->"+it->first,flowTotals);
|
|
|
|
flowTotal+=flowRate;
|
|
|
|
flowTotals+="->"+std::to_string(flowTotal);
|
|
|
|
explore(it->first,visitedvalves,flowRate+rooms[it->first].flowValue,minute+rooms[currentRoom].paths[it->first]+1,flowTotal,journey+"->"+it->first,flowTotals);
|
|
|
|
flowTotal=previousFlowTotal;
|
|
|
|
flowTotals=prevFlowTotal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
std::ifstream file("testinput");
|
|
|
|
while (file.good()){
|
|
|
|
std::string line;
|
|
|
|
std::getline(file,line);
|
|
|
|
std::cout<<line<<std::endl;
|
|
|
|
if (line.length()>0){
|
|
|
|
int flowRate=std::atoi(line.substr(line.find('=')+1,line.find(';')-line.find('=')-1).c_str());
|
|
|
|
std::cout<<"Flow Rate: "<<flowRate<<std::endl;
|
|
|
|
std::string valveName=line.substr(line.find(' ')+1,2);
|
|
|
|
std::cout<<"Valve "<<valveName<<std::endl;
|
|
|
|
int marker=line.find(',');
|
|
|
|
Room newRoom;
|
|
|
|
newRoom.name=valveName;
|
|
|
|
newRoom.flowValue=flowRate;
|
|
|
|
if (flowRate>0){
|
|
|
|
targetRooms.push_back(valveName);
|
|
|
|
}
|
|
|
|
while (marker!=std::string::npos){
|
|
|
|
std::string roomName=line.substr(marker-2,2);
|
|
|
|
std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
|
|
|
|
marker=line.find(',',marker+1);
|
|
|
|
newRoom.connections.push_back(roomName);
|
|
|
|
}
|
|
|
|
std::string roomName=line.substr(line.size()-2,2);
|
|
|
|
std::cout<<"Connection w/"<<roomName<<" found"<<std::endl;
|
|
|
|
newRoom.connections.push_back(roomName);
|
|
|
|
rooms[valveName]=newRoom;
|
|
|
|
std::cout<<rooms[valveName]<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::cout<<"Preparing distance cache..."<<std::endl;
|
|
|
|
for (std::map<std::string,Room>::iterator it=rooms.begin();it!=rooms.end();++it){
|
|
|
|
for (std::map<std::string,Room>::iterator it2=rooms.begin();it2!=rooms.end();++it2){
|
|
|
|
if (it->first==it2->first){
|
|
|
|
rooms[it->first].paths[it2->first]=0;
|
|
|
|
//std::cout<<it->first<<"->"<<it2->first<<": 0"<<std::endl;
|
|
|
|
} else {
|
|
|
|
rooms[it->first].paths[it2->first]=findRoute(it->first,it2->first,{},0);
|
|
|
|
//std::cout<<it->first<<"->"<<it2->first<<": "<<rooms[it->first].paths[it2->first]<<std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
permutation(targetRooms,targetRooms.size(),targetRooms.size());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|