algorithm adventures in moving part iv - andstudy/forge GitHub Wiki

Outbreak

문제 μš”μ•½

  • μ΅œλŒ€ 10000Km 거리의 λͺ©ν‘œμ§€ κΉŒμ§€ μ΅œμ†Œμ˜ 기름값을 μ“°λ©΄μ„œ λ„μ°©ν•˜λŠ” 방법은?

문제 ν•΄κ²°

  • μ΅œλŒ€ 10000 + 1 + 100 Km λ₯Ό 인덱슀둜 DP ν…Œμ΄λΈ”μ„ λ§Œλ“¬.
  • 각 μœ„μΉ˜μ—μ„œμ˜ μ΅œμ†Œ 기름값을 κ΅¬ν•΄μ„œ DP ν…Œμ΄λΈ” μ™„μ„±
  • DP ν…Œμ΄λΈ”μ„ λŒλ©΄μ„œ 기름값을 λˆ„μ  μ‹œμΌœλ‚˜κ°€ 닡을 κ΅¬ν•œλ‹€.

μ†Œκ°

  • Wrong ν•œλ²ˆ, Presentation Error ν•œλ²ˆ, Solved.. 였 λŸ­ν‚€!
  • μž…μΆœλ ₯이 κΉŒνƒˆμŠ€λŸ½λ„€μš”;

풀이

    // "Adventures in Moving - Part IV" Solution By Outbreak 
    
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    //#define _TDD
    
    //--------------------------------------------------------------------
    
    namespace Solver
    {
    	static const int IMPOSSIBLE_PRICE = 10000;
    	static const int MAX_DISTANCE = 10001;
    	static const int MAX_GAS_SIZE = 200;
    	static const int DEFAULT_GAS_SIZE = 100;
    
    	static vector<int> VPrice(MAX_DISTANCE+DEFAULT_GAS_SIZE,IMPOSSIBLE_PRICE);
    
    	// 1. > DP ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”
    	void MakePriceTable()
    	{
    		int i;
    
    		for( i=0; i<MAX_DISTANCE+DEFAULT_GAS_SIZE; i++ )
    		{
    			VPrice[i] = IMPOSSIBLE_PRICE;
    		}
    
    		for( i=0; i<=DEFAULT_GAS_SIZE; i++ )
    		{
    			VPrice[i] = 0;
    		}
    	}
    
    	// 2. > DP ν…Œμ΄λΈ” λ§Œλ“€κΈ° - 각 μ£Όμœ μ†Œλ₯Ό μ€‘μ‹¬μœΌλ‘œ!
    	void InsertPrice( int dist, int price )
    	{
    		// ν˜„μž¬ μœ„μΉ˜μ—μ„œ 제일 μ‹Ό 가격
    		for(int i=1;i<=MAX_GAS_SIZE;i++)
    		{
    			if(VPrice[ dist+i ] > price)
    			{
    				VPrice[ dist+i ] = price;
    			}
    		}
    	}
    
    	// 3. > μ΅œμ†Œ λΉ„μš© κ΅¬ν•˜κΈ°
    	int CalcMinimumPrice(int distance)
    	{
    		int price = 0;
    
    		// 각 μœ„μΉ˜μ—μ„œμ˜ 주유 가격을 더해 λ‚˜κ°€λ©΄μ„œ 총 λΉ„μš©μ„ μ‚°μΆœν•œλ‹€.
    		// λ°˜λ‚© μ‹œ κΈ°λ¦„ν†΅μ˜ 반이 μ±„μ›Œμ Έ μžˆμ–΄μ•Ό ν•˜λ―€λ‘œ κ·Έ λ§ŒνΌμ„ 더 κ°„λ‹€κ³  μƒκ°ν•œλ‹€.
    		for(int i=1; i<=distance+DEFAULT_GAS_SIZE; i++) 
    		{
    			if (VPrice[i] == IMPOSSIBLE_PRICE) 
    			{
    				return -1;
    			}
    
    			price += VPrice[i];
    		}
    
    		return price;
    	}
    }
    
    //--------------------------------------------------------------------
    
    namespace Runner
    {
    	void Execute(istream& in, ostream& out)
    	{	
    		int sample = 0;
    
    		in >> sample;
    
    		while( sample-- )
    		{
    			int distance = 0, dist = 0, price = 0;
    
    			in >> distance;
    
    			Solver::MakePriceTable();
    			
    			while(true)
    			{		
    				in.get();
    
    				// κ°œν–‰μ΄ ν•œκ°œ λ”μ˜€λ©΄ λ‹€μŒ μƒ˜ν”Œ 처리
    				if( in.peek() == '\n')
    				{
    					break;
    				}
    
    				in >> dist >> price;					
    
    				if( in.fail() )
    					break;
    
    				Solver::InsertPrice(dist, price);
    			}
    
    			int result = Solver::CalcMinimumPrice(distance);
    
    			if( result == -1 )
    			{
    				out << "Impossible" << endl;
    			}
    			else
    			{
    				out << result << endl;
    			}
    
    			if( sample > 0 )
    			{
    				out << endl;
    			}
    		}
    	}
    }
    
    
    //--------------------------------------------------------------------
    
    #ifdef _TDD
    
    #include "unittest++.h"
    
    struct TEST_BASE
    {
    	stringstream input;
    	stringstream output;
    };
    
    TEST_FIXTURE(TEST_BASE, PresentationTest)
    {
    	input << 
    		"2\n"
    		"\n"
    		"500\n"
    		"100 999\n" 
    		"150 888\n"
    		"200 777\n"
    		"300 999\n"
    		"400 1009\n"
    		"450 1019\n"
    		"500 1399\n";
    
    	input << "\n";
    
    	input << 	
    		"500\n"
    		"100 999\n" 
    		"150 888\n"
    		"200 777\n"
    		"300 999\n"
    		"400 1009\n"
    		"450 1019\n"
    		"500 1399\n";
    
    	Runner::Execute(input, output);
    
    	CHECK_EQUAL( "450550\n\n450550\n", output.str());
    }
    #endif
    
    //--------------------------------------------------------------------
    
    int main()
    {
    
    #ifdef _TDD	
    	UnitTest::RunAllTests();
    #else
    	Runner::Execute(cin, cout);
    #endif // _TDD
    	return 0;
    }

ParkPD

  • μ£Όμœ μ†Œ 듀릴 λ•Œλ§ˆλ‹€ 항상 탱크λ₯Ό 꽉 μ±„μ›Œμ•Ό ν•œλ‹€λŠ” 가정이 μžˆλ‹€λ©΄ 이것도 닡이 될 수 μžˆκ² μ§€λ§Œ, μ—­μ‹œ 무엇을 DP table 둜 λ§Œλ“€ 것인가λ₯Ό 잘 λͺ» μƒκ°ν–ˆλ„€μš”. 쩝...

  • μƒˆλ‘œ ν‘Ό λ¬Έμ œλŠ” μ€€μ„μ”¨λž‘ λ˜‘κ°™μ΄ ν’€μ—ˆκΈ° λ•Œλ¬Έμ— λ”°λ‘œ μ˜¬λ¦¬μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. :)

  • κ·ΈλŸ¬λ‹ˆκΉŒ μ•„λž˜ μ½”λ“œλŠ” 잘 λͺ» ν‘Ό κ±°λΌλŠ” κ±°.. T_T

      /* @JUDGE_ID:parkpd 110401 Cpp "test" */
      
      /* @BEGIN_OF_SOURCE_CODE */
      
      #include <iostream>
      #include <vector>
      #include <set>
      #include <deque>
      #include <list>
      #include <stack>
      #include <string>
      #include <algorithm>
      #include <map>
      #include <limits>
      #include <assert.h>
      #include <iomanip>
      #include <math.h>
      
      #define _UNIT_TEST
      
      #ifdef _UNIT_TEST
      #include <Windows.h>
      #endif
      
      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';
      	}
      
      #ifdef _UNIT_TEST
      	class CStopWatch
      	{
      	public:
      		CStopWatch()
      		{
      			m_StartTick = GetTickCount();		// gcc μ—μ„œ μ•ˆ 될 수 μžˆμœΌλ‹ˆκΉŒ
      		}
      
      		~CStopWatch()
      		{
      			cout << "Time passed : " << GetTickCount() - m_StartTick << " milisec.\n";
      		}
      
      		int m_StartTick;
      	};
      #endif
      
      	typedef map<int, int> IntDB;
      	typedef vector<int> Ints;
      	typedef list<int> IntList;
      
      };
      
      using namespace ATUtil;
      
      #ifdef _UNIT_TEST
      
      #include "../UnitTest++/src/UnitTest++.h"
      
      #ifdef max
      #undef max
      #endif
      
      #ifdef min
      #undef min
      #endif
      
      int main()
      {
      	UnitTest::RunAllTests();
      
      	char temp;
      	cin >> temp;
      
      	return 0;
      }
      
      #endif
      
      // code implement
      
      namespace ATCode
      {
      	//////////////////////////////////////////////////////////////////////////
      	// CStation
      	class CStation
      	{
      	public:
      		CStation(int d, int c) : m_Dist(d), m_Cost(c), m_TotalCost(0) {}
      
      		int m_Dist;
      		int m_Cost;
      		int m_TotalCost;
      	};
      
      	//////////////////////////////////////////////////////////////////////////
      	// CStationNavi
      	class CStationNavi
      	{
      	public:
      		enum {MAX_STATIONS = 9};
      
      		// 100 μ΄μƒμ˜ μ—°λ£Œλ₯Ό 남기기 μœ„ν•΄, μ•„μ˜ˆ 거리λ₯Ό λŠ˜λ €μ€€λ‹€.
      		CStationNavi(int dist) : m_Dist(dist + 100)
      		{
      			// μΆœλ°œμ§€λ„ μΌμ’…μ˜ μ£Όμœ μ†Œλ‘œ μƒκ°ν•˜μž.
      			// 미리 κ°€μ§€κ³  μžˆλŠ” κ°€μŠ€ 100 λ§ŒνΌμ„ λΊ€ κ±°λ¦¬μ—μ„œ κ°€μŠ€ 200 을 채웠닀고 μƒκ°ν•˜κ³  μ‹œμž‘ν•œλ‹€.
      			Input(-100, 0);
      		}
      
      		void Input(int d, int c) 
      		{
      			m_Stations.push_back(CStation(d, c));
      		}
      
      		template<typename InputIterator>
      		void Inputs(InputIterator f, InputIterator t) 
      		{
      			for (InputIterator i = f; i < t; i += 2)
      			{
      				Input(*i, *(i+ 1));
      			}
      		}
      
      		int CalcDirectCost(int from, int to)
      		{
      			if (-1 == m_CostTable[from][to])
      			{
      				const int distBetweenStation = m_Stations[to].m_Dist - m_Stations[from].m_Dist;
      				if (200 < distBetweenStation)
      				{
      					m_CostTable[from][to] = numeric_limits<int>::max();	// 갈 수 μ—†μŒ.
      				}
      				else
      				{
      					m_CostTable[from][to] = m_Stations[from].m_Cost * (distBetweenStation);
      				}
      			}
      
      			return m_CostTable[from][to];
      		}
      
      		int CalcCost(int from, int to)
      		{
      			// TODO : κ°€μŠ€κ°€ λΆ€μ‘±ν•˜λ©΄ λ¬΄ν•œλŒ€λ₯Ό 리턴해야 ν•œλ‹€. μ–΄λ–»κ²Œ?
      
      			// Cs-t = min(Cs-t, min(k=s-t)(Cs-k, Ck-t))
      			if ((from == to) || (from + 1 == to))
      			{
      				return CalcDirectCost(from, to);
      			}
      			else
      			{
      				// Cs-t = min(Cs-t, min(k=s-t)(Cs-k, Ck-t))
      				int minCost = numeric_limits<int>::max();
      				for (int k = from + 1; k < to; ++k)
      				{
      					int cost = CalcCost(from, k) + CalcCost(k, to);
      					if (cost < minCost)
      					{
      						minCost = cost;
      					}
      				}
      
      				m_CostTable[from][to] = min(CalcDirectCost(from, to), minCost);
      				return m_CostTable[from][to];
      			}
      		}
      
      		int Calc()
      		{
      			Input(m_Dist, 0);		// λͺ©μ μ§€λ„ μΌμ’…μ˜ μ£Όμœ μ†Œλ‘œ μƒκ°ν•˜μž.
      
      			// Cs-t = min(Cs-t, min(k=s-t)(Cs-k, Ck-t))
      
      			// case 1.
      			// C0-2 = min(C0-2, C0-1 + C1-2)
      
      			for (int r = 0; r < MAX_STATIONS; ++r)
      			{
      				for (int c = 0; c < MAX_STATIONS; ++c)
      				{
      					if (r == c)
      					{
      						m_CostTable[r][c] = 0;
      					}
      					else
      					{
      						m_CostTable[r][c] = -1;
      					}
      				}
      			}
      
      			const int numStations = (int)m_Stations.size();
      			int calcCost = 0;
      			for (int diagonal = 1; diagonal <= numStations; ++diagonal)
      			{
      				for (int r = 0; r < numStations - diagonal; ++r)
      				{
      					int c = r + diagonal;
      					//cout << r << c << "\n";
      					//m_CostTable[r][c] = 
      						//min(m_CostTable[r][c], 
      							//min(k)(m_CostTable[r][k] + m_CostTable[k][c]);
      					calcCost = CalcCost(r, c);
      					m_CostTable[r][c] = calcCost;
      				}
      			}
      			
      			return m_CostTable[0][numStations - 1];
      		}
      
      		int m_Dist;
      		vector<CStation> m_Stations;
      
      		int m_CostTable[MAX_STATIONS][MAX_STATIONS];
      	};
      
      	///////////////////////////////////////////////////////////////
      	// CConsole
      	class CConsole
      	{
      	public:
      		static void ConsoleTest(istream& input, ostream& output);
      	};
      
      	void CConsole::ConsoleTest(istream& input, ostream& output)
      	{
      		int testCount = 0;
      		input >> testCount;
      
      		for (int i = 0; i < testCount; ++i)
      		{
      			if (1 <= i)
      			{
      				output << "\n";
      			}
      
      			int dist;
      			input >> dist;
      
      			CStationNavi navi(dist);
      
      			int pos, price;
      			while (input >> pos >> price)
      			{
      				navi.Input(pos, price);
      			}
      
      			output << navi.Calc() << "\n";
      		}
      	};
      
      }
      
      using namespace ATCode;
      
      #ifndef _UNIT_TEST
      
      int main()
      {
      	CConsole::ConsoleTest(cin, cout);
      
      	return 0;
      }
      
      #else
      
      // tests
      
      struct FixtureBase
      {
      	FixtureBase()
      	{
      	}
      
      	stringstream input;
      	stringstream output;
      };
      
      TEST_FIXTURE(FixtureBase, Case2)
      {
      	int stations[] = {100, 999, 200, 1000};
      	CStationNavi n(300);
      	n.Inputs(&stations[0], &stations[sizeof(stations) / sizeof(int)]);
      	CHECK_EQUAL(0, n.Calc());
      }
      
      TEST_FIXTURE(FixtureBase, Case1)
      {
      	int stations[] = {50, 999};
      	CStationNavi n(100);
      	n.Inputs(&stations[0], &stations[sizeof(stations) / sizeof(int)]);
      	CHECK_EQUAL(0, n.Calc());
      }
      
      TEST_FIXTURE(FixtureBase, ConsoleTest)
      {
      	input << 
      		"1\n"
      		"\n"
      		"500\n"
      		"100 999\n"
      		"150 888\n"
      		"200 777\n"
      		"300 999\n"
      		"400 1009\n"
      		"450 1019\n"
      		"500 1399\n";
      	CConsole::ConsoleTest(input, output);
      	CHECK_EQUAL( 
      		"450550\n", 
      		output.str());
      }
      
      #endif
      
      /* @END_OF_SOURCE_CODE */
    
⚠️ **GitHub.com Fallback** ⚠️