algorithm the tourist guide - andstudy/forge GitHub Wiki

Outbreak

문제 μš”μ•½

  • λͺ‡κ°œμ˜ λ…Έλ“œλ₯Ό κ±°μΉ˜λŠ”μ§€ 상관 없이 μ΅œλŒ€ λŒ€μ—­ν­μœΌλ‘œ λͺ©μ μ§€κΉŒμ§€ 데이터 μ „μ†‘ν•˜λŠ” 문제
  • λͺ‡λ²ˆλ§Œμ— 데이터 전솑을 마칠 수 μžˆλŠ”κ°€?

문제 ν•΄κ²°

  • DFS κ·Έλž˜ν”„ 순회λ₯Ό ν†΅ν•œ μ΅œλŒ€ λŒ€μ—­ν­ μ°ΎκΈ°
  • μž…λ ₯ λ…Έλ“œκ°€ 100개 이상이 될 수 μžˆμœΌλ―€λ‘œ, 효율적인 DFS μ°ΎκΈ°λ₯Ό ν•˜λŠ”λ°, DP 이용
  • μΈμ›μˆ˜μ— μ•½κ°„μ˜ 트릭이 μžˆμ—ˆμŒ

κ³„νš

  • 내일 이 μ½”λ“œλ₯Ό 예쁘게 λ§Œλ“€μ–΄ 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€~
  • 내일은 μΉ νŒμ„ 많이 써야 ν•  것 κ°™μ•„μš”~ γ„±γ„±

풀이

    using System;
    using System.Collections.Generic;
    using System.Text;
    using NUnit.Framework;
    
    namespace ACM_TheTouristGuide
    {
        class Program
        {
            public static int[,] input = 
            {
                { 1, 2, 30 },
                { 1, 3, 15 },
                { 1, 4, 10 },
                { 2, 4, 25 },
                { 2, 5, 60 },
                { 3, 4, 40 },
                { 3, 6, 20 },
                { 4, 7, 35 },
                { 5, 7, 20 },
                { 6, 7, 30 }
            };
            static void Main(string[] args)
            {
                // DP 생성
                  int nodeCnt = 7 + 1;
                int[,] dp = new int[nodeCnt,nodeCnt];
                int rowCnt = input.GetLength(0);
                int colCnt = input.GetLength(1);
    
                for (int i = 0; i < rowCnt; i++)
                {
                    int src = input[i, 0];
                    int dst = input[i, 1];
                    int val = input[i, 2];
                    dp[src, dst] = val;
                    dp[dst, src] = val;
                }
    
                // DP 확인
                  for (int i = 1; i < dp.GetLength(0); i++)
                {
                    for (int j = 1; j < dp.GetLength(1); j++)
                    {
                        Console.Write("{0:d2} ", dp[i, j]);
                    }
                    Console.WriteLine();
                }
    
                Console.WriteLine();
    
                // DP κ°±μ‹ ν•˜κΈ°
                  for (int i = 1; i < dp.GetLength(0); i++)
                {
                    for (int j = 1; j < dp.GetLength(1); j++)
                    {
                        if (i == j)
                            continue;
    
                        if (dp[i, j] == 0)
                            continue;
    
                        int src = i;
                        int dst = j;
    
                        // dst μ—μ„œ 갈 수 μžˆλŠ” 1단계 더 μ „μ§„
                          for (int newDst = 1; newDst < dp.GetLength(1); newDst++)
                        {
                            // src -> dst -> newDst
                            if (newDst == src)
                                continue;
    
                            if (dp[dst, newDst] == 0)
                                continue;
    
                            // src -> dst 의 λŒ€μ—­ν­μ΄ 더 μž‘μ„ λ•Œ!
                            // dp[src, newDst] λŠ” src->dst->newDst λ₯Ό μ˜λ―Έν•œλ‹€.
                            int max = dp[src, newDst];
                            if (dp[src, dst] < dp[dst, newDst])
                            {
                                if (max < dp[src, dst])
                                    dp[src, newDst] = dp[src, dst];
                            }
                            else
                            {
                                if (max < dp[dst, newDst])
                                    dp[src, newDst] = dp[dst, newDst];
                            }
                        }
                    }
                    
                }
    
                // DP 확인
                  for (int i = 1; i < dp.GetLength(0); i++)
                {
                    for (int j = 1; j < dp.GetLength(1); j++)
                    {
                        Console.Write("{0:d2} ", dp[i, j]);
                    }
                    Console.WriteLine();
                }
    
                // λ¬Έμ œν’€μ΄
                  int μΆœλ°œμ§€ = 1;
                int 도착지 = 7;
                int 총인원 = 101; //μ™œ 101μΌκΉŒμš”?? 흐흐
    
                Console.WriteLine("\n{0} 번 μ™”λ‹€κ°”λ‹€ ν•΄μ•Ό ν•©λ‹ˆλ‹€.", 
                    System.Math.Ceiling((float)총인원/(float)dp[μΆœλ°œμ§€, 도착지]));
            }
        }
    
        [TestFixture]
        public class UnitTest
        {
            [SetUp]
            public void SetUp()
            {
                Console.WriteLine("");
            }
    
            [Test]
            public void MakeDP()
            {
            }
    
            [TearDown]
            public void TearDown()
            {
                Console.WriteLine("");
            }
        }
    }

ParkPD

  • Wrong Answer κ°€ λ‚˜μ˜€λ„€μš”. 쩝.. 뭐가 λ¬Έμ œκ°€ μžˆλŠ”κ±° 같은데 λ­˜κΉŒμš”.. γ…Žγ…Ž

      /* @JUDGE_ID:parkpd 110401 Cpp "test" */
      
      /* @BEGIN_OF_SOURCE_CODE */
      
      #include <iostream>
      #include <vector>
      #include <set>
      #include <string>
      #include <strstream>
      #include <algorithm>
      #include <map>
      #include <math.h>
      
      //#define _UNIT_TEST
      
      using namespace std;
      
      namespace ATUtil
      {
      
      bool IsInRange(int value, int from, int to)
      {
      	return (from <= value) && (value <= to);
      }
      
      int ConvertToIndex(char c)
      {
      	if ('a' <= c && c <= 'z')
      	{
      		return c - 'a';
      	}
      	else
      	{
      		return -1;
      	}
      }
      
      char ConvertToChar(int i)
      {
      	return (char)i + 'a';
      }
      
      typedef map<int, int> IntDB;
      typedef vector<int> Ints;
      
      };
      
      using namespace ATUtil;
      
      #ifdef _UNIT_TEST
      
      #include "../UnitTest++/src/UnitTest++.h"
      
      int main()
      {
      	UnitTest::RunAllTests();
      
      	char temp;
      	cin >> temp;
      
      	return 0;
      }
      
      #endif
      
      // code implement
      
      namespace ATCode
      {
      
      ///////////////////////////////////////////////////////////////
      // CTourGuide
      class CTourGuide
      {
      public:
      	CTourGuide() : m_Start(-1), m_Destiny(-1), m_Max(0), m_CityNum(0) {}
      
      	void Init(int cities, int roads);
      	void Connect(int from, int to, int capacity);
      	int NeedTrip(int start, int destiny, int tourists);
      	void _FindMaxTrip(int start);
      
      	struct Road
      	{
      		Road(int to, int capacity) : m_To(to), m_Capacity(capacity) {}
      		int m_To;
      		int m_Capacity;
      	};
      
      	struct City
      	{
      		City(int index) : m_Index(index), m_Checked(false), m_MaxCapacity(-1) {}
      
      		int m_Index;
      		bool m_Checked;
      		int m_MaxCapacity;
      		vector<Road> m_Neighbor;
      	};
      
      	int m_Start;
      	int m_Destiny;
      
      	int m_Max;
      
      	int m_CityNum;
      	vector<City> m_Cities;
      };
      
      void CTourGuide::Init(int cities, int roads)
      {
      	m_Cities.reserve(cities + 1);
      	m_Cities.push_back(City(-1));	// dummy
      	for (int i = 1; i <= cities; ++i)
      	{
      		m_Cities.push_back(City(i));
      	}
      
      	m_CityNum = cities;
      }
      
      void CTourGuide::Connect(int from, int to, int capacity)
      {
      	// bi-direction
      	m_Cities[from].m_Neighbor.push_back(Road(to, capacity));
      	m_Cities[to].m_Neighbor.push_back(Road(from, capacity));
      }
      
      int CTourGuide::NeedTrip(int start, int destiny, int tourists)
      {
      	m_Start = start;
      	m_Destiny = destiny;
      
      	City& s = m_Cities[m_Start];
      	s.m_MaxCapacity = 0x7fffffff;
      	
      	_FindMaxTrip(m_Start);
      
      	double maxTripCapacity = (double)(m_Cities[m_Destiny].m_MaxCapacity - 1);
      	int trip = (int)ceil(tourists / maxTripCapacity);
      	return trip;
      }
      
      void CTourGuide::_FindMaxTrip(int start)
      {
      	City& s = m_Cities[start];
      	if (s.m_Checked)
      	{
      		return;
      	}
      
      	s.m_Checked = true;
      
      	vector<int> needCheckRoads;
      
      	for (size_t i = 0; i < s.m_Neighbor.size(); ++i)
      	{
      		Road& toRoad = s.m_Neighbor[i];
      		City& toCity = m_Cities[toRoad.m_To];
      
      		if (toCity.m_Checked)
      		{
      			continue;
      		}
      
      		const int possibleCapacity = min(s.m_MaxCapacity, toRoad.m_Capacity);
      
      		// ν˜„μž¬ λ„μ‹œμ˜ μˆ˜μš©λŸ‰μ΄ 이전 λ„μ‹œκΉŒμ§€μ˜ μˆ˜μš©λŸ‰ + λ„λ‘œκ°€ λ„“λ‹€λ©΄ ok			
      		if (possibleCapacity <= toCity.m_MaxCapacity)
      		{
      			// do nothing
      		}
      		// ν˜„μž¬ λ„μ‹œμ˜ μˆ˜μš©λŸ‰λ³΄λ‹€ 이전 λ„μ‹œκΉŒμ§€μ˜ μˆ˜μš©λŸ‰ + λ„λ‘œκ°€ λ„“λ‹€λ©΄ 이걸 선택
      		else
      		{
      			toCity.m_MaxCapacity = possibleCapacity;
      		}
      
      		if (toCity.m_Index == m_Destiny)
      		{
      			continue;
      		}
      
      		needCheckRoads.push_back(toRoad.m_To);
      	}
      
      	for (size_t i = 0; i < needCheckRoads.size(); ++i)
      	{
      		_FindMaxTrip(needCheckRoads[i]);
      	}
      }
      
      ///////////////////////////////////////////////////////////////
      // CConsole
      class CConsole
      {
      public:
      	static void ConsoleTest(istream& input, ostream& output);
      };
      
      void CConsole::ConsoleTest(istream& input, ostream& output)
      {
      	int scenarioIndex = 1;
      
      	while (1)
      	{
      		int cities = 0;
      		int roads = 0;
      	
      		input >> cities >> roads;
      
      		if ((0 == cities) && (0 == roads))
      		{
      			break;
      		}
      
      		CTourGuide tourGuide;
      		tourGuide.Init(cities, roads);
      
      		int from = 0;
      		int to = 0;
      		int capacity = 0;
      
      		for (int i = 0; i < roads; ++i)
      		{
      			input >> from >> to >> capacity;
      			tourGuide.Connect(from, to, capacity);
      		}
      
      		int start;
      		int destiny;
      		int tourists;
      		input >> start >> destiny >> tourists;
      
      		output << "Scenario #" << scenarioIndex << "\n";
      		output << "Minimum Number of Trips = " << tourGuide.NeedTrip(start, destiny, tourists) << "\n";
      	}
      };
      
      }
      
      using namespace ATCode;
      
      #ifndef _UNIT_TEST
      
      int main()
      {
      	CConsole::ConsoleTest(cin, cout);
      
      	return 0;
      }
      
      #else
      
      // tests
      
      struct FixtureConsole
      {
      	stringstream input;
      	stringstream output;
      };
      
      TEST_FIXTURE(FixtureConsole, ConsoleTest1)
      {
      	input << 
      		"7 10\n"
      		"1 2 30\n"
      		"1 3 15\n"
      		"1 4 10\n"
      		"2 4 25\n"
      		"2 5 60\n"
      		"3 4 40\n"
      		"3 6 20\n"
      		"4 7 35\n"
      		"5 7 20\n"
      		"6 7 30\n"
      		"1 7 99\n"
      		"0 0\n"
      	;
      	CConsole::ConsoleTest(input, output);
      	CHECK_EQUAL("Scenario #1\nMinimum Number of Trips = 5\n", output.str());
      }
      
      TEST_FIXTURE(FixtureConsole, ConsoleTest2)
      {
      	input << 
      		"7 12\n"
      		"1 2 30\n"
      		"1 3 25\n"
      		"1 4 40\n"
      		"2 3 80\n"
      		"2 7 25\n"
      		"7 6 20\n"
      		"3 4 70\n"
      		"5 3 45\n"
      		"6 5 30\n"
      		"7 5 60\n"
      		"3 7 15\n"
      		"4 6 25\n"
      		"1 6 100\n"
      		"0 0\n"
      	;
      	CConsole::ConsoleTest(input, output);
      	CHECK_EQUAL("Scenario #1\nMinimum Number of Trips = 4\n", output.str());
      }
      
      
      #endif
      
      /* @END_OF_SOURCE_CODE */
    

kukuman

  • Graph

      import java.util.ArrayList;
      
      
      public class Graph {
      	private int pointCount;
      	private int[][] nodes;
      	
      	public Graph(int pointCount) {
      		this.pointCount = pointCount;
      		nodes = new int[pointCount][pointCount];
      		for(int i=0;i<pointCount;i++){
      			for(int j=0;j<pointCount;j++){
      				nodes[i][j] = 0;
      			}
      		}
      	}
      	
      	
      	public void insertNode(int fromPoint, int toPoint, int weight) {
      		nodes[fromPoint][toPoint] = weight;
      		nodes[toPoint][fromPoint] = weight;
      		
      	}
      	public Path findMinPath(int fromPoint,int toPoint){
      		Path newPath= new Path(fromPoint);
      		return findMinPath( fromPoint, toPoint, newPath);
      	}
      	public Path findMinPath(int fromPoint,int toPoint,Path path){
      		if(fromPoint == toPoint){
      			return path;
      		}
      		ArrayList<Path> resultPaths = new ArrayList<Path>();
      		for(int i=0;i<pointCount;i++){
      			//검사할 λ…Έλ“œκ°€ μ—°κ²°λ˜μ–΄ 있고  이전에 λ°©λ¬Έν•˜μ§€ μ•Šμ•˜λ˜ λ…Έλ“œμ΄λ©΄ λ‹€μŒ λ…Έλ“œλ‘œ λΆ€ν„° 탐색
      			if( nodes[fromPoint][i] > 0 ){
      				if(path.isVisitedNode(i)){
      					continue;
      				}
      				Path newPath = new Path(path);
      				newPath.addVisitedPoint(i, nodes[fromPoint][i]);
      				
      				Path searchedPath = findMinPath(i, toPoint,newPath);
      				if(searchedPath != null){
      					resultPaths.add(searchedPath);
      				}
      			
      			}
      		}
      		
      		Path minPath = null;
      		int minWeight = Integer.MAX_VALUE;
      		//κ°€μž₯ 짧은 Path μ°Ύμ•„μ„œ return
      		for(int i=0;i<resultPaths.size();i++){
      			Path curPath = resultPaths.get(i);
      			if(curPath.getPathWeight() < minWeight){
      				minPath = curPath;
      				minWeight = curPath.getPathWeight();
      			}
      		}
      		return minPath;
      	}
      
      }
    
  • Path

      import java.util.ArrayList;
      
      
      public class Path {
      	private ArrayList<Integer> visitedPoint = new ArrayList<Integer>();
      	private int pathWeight =Integer.MAX_VALUE;
      	
      	public Path(Path fromPath){
      		visitedPoint.addAll(fromPath.visitedPoint);
      		pathWeight = fromPath.pathWeight;
      	}
      	
      	public Path(int fromPoint){
      		visitedPoint.add(fromPoint);
      	}
      	
      	public void addVisitedPoint(int point,int weight){
      		visitedPoint.add(point);
      		pathWeight = Math.min(pathWeight, weight);
      	}
      	public int getPathWeight() {
      		return pathWeight;
      	}
      	public void setPathWeight(int pathWeight) {
      		this.pathWeight = pathWeight;
      	}
      	
      	public boolean isVisitedNode(int point){
      		return visitedPoint.contains(point);
      	}
      	
      	public String toString(){
      		return "Paths : "+visitedPoint.toString()+"\nWeight:"+pathWeight;
      	}
      }
    
  • TestCase

      import junit.framework.TestCase;
      
      
      public class GraphTestCase extends TestCase {
      	public void testInitGraph(){
      		Graph graph = new Graph(3);
      		graph.insertNode(0,1,10);
      		graph.insertNode(1,2,20);
      		graph.insertNode(2,0,30);
      		
      		Path minPath = graph.findMinPath(0, 2);
      		System.out.println(minPath);
      	}
      }
    
⚠️ **GitHub.com Fallback** ⚠️