SlideShare a Scribd company logo
ENHANCE YOUR
FUNDAMENTAL SKILLS
2015 NCTU WINTER CAMP :: DAY 2
ABOUT THE LECTURER
• Name: lnishan.
• Undergraduate, NCTU CS 106.
• 9 years of competitive programming experience.
OUTLINES FOR TODAY'S COURSE
• C/C++ Essentials
• Brute force & Simulation
• Useful techniques
• ad hoc
• Enumeration
C/C++ ESSENTIALS
HANDY SYNTAXES AND COMMON PITFALLS
BASIC I/O
• cin / cout are absurdly slow.
• ~10x slower than scanf / printf
• For test cases with 10+ MB in size, you would spend an unreasonable amount
of time on I/O.
SCANF / PRINTF
format: a char string with "specifiers" and other characters
specifiers: indicate a type of variable
Examples
• scanf("%d%d", &a, &b); // read 2 integers
• printf("%.2f: %.5f", f1, f2); // print 2 floating point numbers:
scanf( format, pointer of variable 1, pointer of variable 2, …
printf( format, variable 1, variable 2, …
SCANF / PRINTF: SPECIFIERS
scanf printf
int %d
long long int %lld *
unsigned int %u
unsigned long long int %llu *
float %f
double %lf
char string %s
int %d
long long int %lld *
unsigned int %u
unsigned long long int %llu *
float %f
double %f
char string %s
* On Windows XP: long long int = %I64d, rather than %lld.
Common pitfalls
• double remains %f in printf()
• Do NOT use %c for char
DEALING WITH ARBITRARY NUMBER OF ELEMENTS
IN A SINGLE LINE
• Sometimes, problems (esp. in the old days) love to play tricks with I/O.
• Suppose the input says you'll be given arbitrary numbers in a single line.
• strtok(): #include <cstring>, atoi(): #include <cstdlib>
1 4 9
4 3 10 15
6 5
14
32
11
Add them up ?
• int ans;
char *ptr;
char s[1000];
while (gets(s)) {
ans = 0;
ptr = strtok(s, " ");
while (ptr != NULL) {
ans += atoi(ptr);
ptr = strtok(NULL, " ");
}
printf("%dn", ans);
}
OTHER STL THAT WOULD HELP YOU WITH I/O
sscanf( string, format, pointer of variable 1, pointer of variable 2, …
sprintf( string, format, variable 1, variable 2, …
sscanf( stringTime, "%d:%d:%d", &h, &m, &s );
• sscanf / sprintf: These 2 are essentially the same as scanf / printf, except the
operations are done on the string, rather than stdin / stdout.
ssprintf( stringTime, "%d:%d:%d", h, m, s );
scanf(" ");
• Get rid of redundant characters (such as newline 'n') in the input buffer.
COMMON PITFALL: STACK OVERFLOW
• What is "Stack Overflow"?
- Exceeded maximum system stack size
• Key notes: Do NOT declare big arrays in local scopes
• Solutions:
1. Declare arrays in global scope
2. std::vector
3. Dynamic arrays (not recommended)
STD::VECTOR
• Think of it as a variable-length array. Its size can be altered during run time.
• Size is 0 initially. (resize or add elements in before using it)
• #include <vector>
vector< member type > myVec;
myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4]
int int int int int
● ● ●
• Declaration
vector<int> myVec;
STD::VECTOR (CONT.)
myVec.push_back( element );
myVec myVec[0] myVec[1] myVec[2]
1 2 3
myVec.resize( size );
myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4]
1 2 3 int int
• Add an element to the back of the array (vector)
myVec.push_back(1); myVec.push_back(2); myVec.push_back(3);
• Resize the vector
myVec.resize(5);
STD::VECTOR (CONT.)
myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4]
1 2 3 int int
myVec.size()
myVec.clear();
• Access elements like it's an array.
• Get the size of the vector
for (int i = 0; i < myVec.size(); i++)
printf("%dn", myVec[i]);
• Clear the vector
myVec.clear();
BRUTE FORCE & SIMULATION
"HOW DIFFICULT CAN THIS BE?" - ME 2009
TOOLS & PRACTICES RECOMMENDED HAVING
• Basic OOP: struct, operator overloading
• Basic pointer operations
• Good naming conventions
STRUCT & OPERATOR OVERLOADING
• Think of struct as a self-created data type. The data type can contain several
member variables and functions.
• struct Matrix
{
int mat[4][4];
Matrix operator + (Matrix &rhs);
Matrix operator * (Matrix &rhs);
};
• Useful in a lot of conditions
CLASSIFICATIONS 分類
• Courtesy of Prof. Yonghui Wu
• 1. Descriptive simulation 直敘式模擬
• 2. Screening simulation 篩選法模擬
• 3. Constructive simulation 構造法模擬
直敘式模擬
• 直敘式模擬就是按照題目要求進行模擬。
• 雖然不需要什麼精妙演算法,但程式設計者一定要忠實於原題,認真審
題,千萬不要疏漏任何條件,精心設計方便類比的資料結構。
• “直敘式模擬”的難度取決於類比物件所包含的動態變化的屬性有多少,
動態屬性愈多,則難度愈大。
• 直敘式模擬的形式一般有兩種
• (1) 按指令行事,一般採用命令序列分析法
• (2) 按時間順序模擬,一般採用時間序列分析法
THE HARDEST PROBLEM EVER
• Source: ACM South Central USA 2002
• Online Judge: POJ 1298、ZOJ 1392、UVA 2540
• Problem description: Decrypt a string by shifting each alphabetical character
by -5.
THE HARDEST PROBLEM EVER (中文翻譯)
• 凱撒大帝(Julius Caesar)生活在充滿了危險和陰謀的年代,他要面臨在最困
難的情況下讓自己生存下來的問題。為了能夠生存,他創建了第一套密碼。
這個密碼聽起來是如此地令人難以置信,以至於沒有人能弄清楚它是如何工
作的。
• 您是凱撒軍隊中的一名下級軍官。您的工作是破譯凱撒發來的郵件,並報告
給您的將軍。凱撒加密的方法很簡單。對於原文中的每一個字母,用這個字
母之後的第五個字母來替換(即,如果原文的字母是“A”,則要替換為密碼
字母“F”)。因為您是要把凱撒的郵件翻譯為原文檔,所以您要做相反的事
情(由將密碼轉換為原文):
• 密碼字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
• 原文字母:V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
• 在密碼檔中只有字母才被替換,其他的非字母字元保持不變,所有的英文字
母為大寫。
THE HARDEST PROBLEM EVER (輸入輸出)
• 輸入:
本問題的輸入由多達100個(非空的)測試用例組成。每個測試用例格式
如下描述,在測試用例之間沒有空行分開。所有的字元為大寫。
一個測試用例由3部分組成:
起始行 —— 一行,“START”
密碼消息 —— 一行,由100到200個字元組成,包含100和200,表示由凱
撒發送來的一條消息。
結束行 —— 一行,“END”
在最後一個測試用例後,給出一行,“ENDOFINPUT”。
• 輸出:
對每個測試用例,輸出一行,給出凱撒的原始資訊。
THE HARDEST PROBLEM EVER (題目解析)
• 按指令行事的簡單直敘式模擬題。按照加密規則,26個大寫英文字母依
序圍成一圈,密碼字母逆時針方向上的第5個字母即為原文字母,即
• 原文字母 = 'A'+(密碼字母- 'A'+21)% 26
• 按照上述規則,依次解密密碼檔中的大寫字母,即可得到原文。
SPEED LIMIT
• Source: ACM Mid-Central USA 2004
• Online Judge: POJ 2017, ZOJ 2176, UVA 3059
• Problem description:
• Given the speed of Bill and Ted in different time periods, calculate the total
distance driven
SPEED LIMIT (中文翻譯)
• Bill和Ted踏上行程,但他們汽車的里程表壞了,因此他們不知道他們駕車
走了多少英里。幸運的是,Bill有一個正在運行的跑錶,因此他們可以記
錄他們的速度和駕駛了多少時間。然而,這個跑錶記錄的方式有些古怪,
因此他們需要計算總的駕駛距離。請你編寫一個程式完成這項計算。
• 例如,他們的跑錶顯示如下:
每小時速度 (英里) 總共經歷時間 (小時)
20 2
30 6
10 7
• 這表示開始的2小時他們以20英里的時速行駛,然後的6-2=4小時他們以30
英里的時速行駛,再以後的7-6=1小時他們以10英里的時速行駛,所以行
駛的距離是(2)(20) + (4)(30) + (1)(10) = 40+120+10=170英里。總的時間耗費
是從他們旅行開始進行計算,而不是從跑錶開始計數開始計算。
SPEED LIMIT (輸入輸出)
• 輸入:
• 輸入由一個或多個資料集合組成。每個資料集合開始的第一行為一個整
數n,1≤n≤10;後面是n對值,每對一行。每對的第一個值s是時速,第二
個值t是總的耗費時間。s和t都是整數,1 ≤s≤90並且1≤t≤12。t的值總是增
序。n的值取-1表示輸入結束。
• 輸出:
• 對於每一個資料集合,輸出行駛距離,然後空格,輸出單詞"miles"。
SPEED LIMIT (題目解析)
• 本題是一道十分簡單的直敘式模擬題,計算過程就是模擬跑錶的運行來
計算總里程:若上一個記錄的駕駛時間為lt,目前記錄的速度為s、駕駛
時間為t,則當前跑的距離為(t - lt) *s ,將該距離累計入總里程。
RIDE TO SCHOOL
• Source: ACM Beijing 2004 Preliminary
• Online Judge: POJ 1922, ZOJ 2229
• Problem description:
• Students ride bikes from Wanliu to Yanyuan starting at different time with
different but fixed speeds. Charley however, ride bikes in an unusual way. He
stays still initially. Once being surpassed, he would speed up to follow that
surpasser.
• Find out when Charley reaches Yanguan given all the info mentioned above.
RIDE TO SCHOOL (中文翻譯)
• 北京大學的許多研究生住在萬柳校區,距離主校區燕園校區有4.5公里。
住在萬柳的同學或者乘坐巴士,或者騎自行車去主校區上課。由於北京
糟糕的交通,許多同學選擇騎自行車。
• 我們假定除了Charley以外,所有的同學從萬柳到燕園都是以某一個確定
的速度騎自行車。Charley則有一個不同的騎車習慣——他總是要跟在另一
個騎車同學的後面,以免一個人獨自騎車。當Charley到萬柳校區的大門
口的時候,他就等待離開萬柳去燕園的同學。如果他等到這樣的同學,
他就騎車跟著這位同學;如果沒有這樣的同學,他就等待去燕園的同學
出現,然後騎車跟上。在從萬柳到燕園的路上,如果有騎得更快的同學
超過了Charley,他就離開原先他跟著的同學,加速跟上騎得更快的同學。
• 假設Charley到萬柳校區的大門口的時間為0,給出其他同學離開萬柳的時
間和速度,請你給出Charley到達燕園的時間。
RIDE TO SCHOOL (輸入輸出)
• 輸入:
• 有幾組測試用例,每組測試用例的第一行為N (1 ≤ N ≤ 10000),表示除了
Charley外,騎車同學的數量。以N=0表示輸入結束。每組測試用例的第一
行後面的N行表示N個騎車同學的資訊,形式為
• Vi [空格] Ti
• Vi 是一個正整數≤ 40,表示第i個騎車同學的速度(kph,每小時公里數),
Ti 則是第i個騎車同學離開萬柳的時間,是一個整數,以秒為單位。在任
何測試用例中總存在非負的Ti。
• 輸出:
• 對每個測試用例輸出一行:Charley到達的時間。在處理分數的時候進1。
RIDE TO SCHOOL (SOLUTION THOUGHT PROCESS)
• You could just simulate accordingly, but …
• Take a second look.
• Imagine yourself as Charley (Hi Charley !), you're currently riding the bike at
some speed. When you get surpassed (note that this only happens during the
way), you would follow that rider who surpassed you. This essentially turns
you into that rider. Repeat this thought process again when you get surpassed
by another rider. You will realize, in the end, you will become the earliest rider
to arrive at Yanyuan.
• The problem becomes easy once you've realized this, but note that there is a
pitfall: Only consider the riders who start later than you. (ie. ignore riders who
start at negative seconds)
RIDE TO SCHOOL (題目解析)
• 本題沒有數學公式和規律,通過直譯模擬每個同學去往燕園校區的情景,
得出Charley從萬柳校區到燕園校區的時間。所以對每組測試資料,從
Charley到萬柳校區的大門的時間0開始計時,求出每個同學到達燕園校區
所用的時間,最少的時間就是Charley從萬柳校區的大門到燕園校區的時
間。
• 設前i-1同學中最早到達燕園校區的時間為min;第i個同學的車速為v,離
開萬柳校區的時間為t,即該同學到達燕園校區的時間x=t+ 4.5*3600/v。
若x<min,則調整min為x。顯然,按照這一方法依次計算所有同學的到達
時間,最後得出的min即為Charley到達的時間。
篩選法模擬
• 模擬過程中可能產生的所有解組成一個篩。
篩選法模擬即先從題意中找出約束條件,然
後將篩中的每一個可能解放到約束條件的篩
檢程式上,一次一次地將不符合條件的解過
濾掉,最後沉澱在篩中的即為問題的解。
• (編按) 白話點講就是,題目對於答案可能有
很多條件必須要逐一檢查;如果過程中全部
條件都符合的話,那這就是一組可行的解答。
好餐廳?
食物好吃?
氣氛佳?
服務親切?
摁 ! 是間好餐廳 !
LOGICAL ERRORS
• 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (?
• 1. 如果味道好吃,我就說這是美食
• 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食
• 判斷餿食?
LOGICAL ERRORS
• 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (?
• 1. 如果味道好吃,我就說這是美食
• 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食
• 判斷餿食?
if (味道難吃 || 聞起來很臭)
這道菜 = 餿食;
LOGICAL ERRORS
• 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (?
• 1. 如果味道好吃,我就說這是美食
• 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食
• 判斷餿食?
如果味道好吃、但聞起來很臭呢 ?
if (味道難吃 || 聞起來很臭)
這道菜 = 餿食;
LOGICAL ERRORS
• 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (?
• 1. 如果味道好吃,我就說這是美食
• 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食
• 判斷餿食?
如果味道好吃、但聞起來很臭呢 ?
if (味道難吃 || (味道難吃 && 聞起來很臭))
if (味道難吃 || 聞起來很臭)
這道菜 = 餿食;
THE GAME
• Source: ACM Tehran Sharif 2004 Preliminary
• Online Judge: POJ 1970, ZOJ 2495
• Problem description: Given a Connect5 board. Determine the state.
THE GAME (中文翻譯)
• 五子棋遊戲是由兩名玩家在一個19*19的棋盤上玩的遊戲。一名玩家執黑,
另一名玩家執白。遊戲開始時棋盤為空,兩名玩家交替放置黑色棋子和
白色棋子。執黑者先走。棋盤上有19條水平線和19條垂直線,棋子放置
在直線的交點上。
• 水平線從上到下標記為1,2,...,19,垂直線從左至右標記為1,2,...,
19。
• 這一遊戲的目標是把5個相同顏色的棋子沿水準,垂直或對角線連續放置。
所以,在圖中執黑的一方獲勝。但是,如果一個玩家將超過五個相同顏
色的棋子連續放置,也不能判贏。
• 基於這一遊戲的棋盤情況,請您寫一個程式,確定是白方贏了比賽,還
是黑方贏了比賽,或者是還沒有一方贏了比賽。輸入資料保證不可能出
現黑方和白方都贏的情況,也沒有白方或黑方在多處獲勝的情況。
THE GAME (輸入輸出)
• 輸入:
• 輸入的第一行包含一個整數t (1≤t≤11),表示測試用例的數目。接下來給
出每個測試用例,每個測試用例19行,每行19個數,黑棋子標識為1,白
棋子標識為2,沒有放置棋子則標識為0。
• 輸出:
• 對每個測試用例,輸出一行或兩行。在測試用例的第一行輸出結果,如
果黑方獲勝,則輸出1;如果白方獲勝,則輸出2;如果沒有一方能獲勝,
則輸出0。如果黑方或白方獲勝,則在第二行給出在5個連續的棋子中最
左邊的棋子水平線編號和垂直線編號(如果5枚連續的棋子垂直排列,則
選最上方棋子的水平線編號和垂直線編號)。
THE GAME (題目解析)
• 初始時所有棋子組成一個篩子。我們由上而下、由左而右掃描每個棋子,分
析其k方向的相鄰棋子(0≤k≤3,0≤i,j≤18,見圖):
篩檢程式中“贏”的約束條件是
• (i,j)k的相反方向的相鄰格(x,y)不同色;
• (i,j)k方向延伸5格在界內;
• 從(i,j)開始,沿k方向連續5格同色且第6格不同色;
若(i,j)的棋子滿足上述約束條件,其顏色所代表的一方贏,(i,j)即為贏方
5個連續的同色棋子中首枚棋子的位置;若檢測了4個方向,(i,j)的棋子依然
不滿足約束條件,則被過濾掉。
若過濾了篩中的所有棋子後篩子變空,則說明沒有一方能獲勝。
構造法模擬
• 構造法類比需要完整精確地構造出反映問題本質的數學模型,根據該模
型設計狀態變化的參數,計算模擬結果。由於數學模型建立了客觀事物
間準確的運算關係,因此其效率一般比較高。
• “構造法模擬”的關鍵是找到數學模型。問題是,能產生正確結果的數
學模型並不是唯一的,從不同的思維角度看問題,可以得出不同的數學
模型,而類比效率和程式設計複雜度往往因數學模型而異。即便有數學
模型,但解該模型的準確方法是否有現成演算法、程式設計複雜度如何,
這些問題需要我們仔細考慮。
PACKETS
• Source: ACM Central Europe 1996
• Online Judge: POJ 1017, ZOJ 1307, UVA 311
• Problem description:
• Given packets with 1*1, 2*2, 3*3, 4*4, 5*5, 6*6 in sizes. Fill these packets into
6*6 parcels.
Find out the minimal number of parcels to be used.
• --- We'll come back to this later
TECHNIQUES
USEFUL TRICKS
DEBUGGING: MAKE USE OF THE DEBUGGER
• A lot of IDEs offer debugger with GUI. Try make the best use of it.
• - Breakpoints
• - Next Line
Code::Blocks 13.12
DEBUGGING: FILE I/O USING STDIN/STDOUT
• File I/O is sometimes useful for debugging in certain circumstances, say you
have a large project or a program that would print out lots of information.
• In such situations, you won't want to modify all the scanf/printf s.
• There are 2 ways that allow you to use File I/O without changing your code.
• 1. freopen()
• 2. Windows command line (CMD)
DEBUGGING: FILE I/O USING STDIN/STDOUT (CONT.)
freopen( input_filename, "r", stdin);
freopen( output_filename, "r", stdin);
Add these lines of code in the beginning.
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
DEBUGGING: FILE I/O USING STDIN/STDOUT (CONT.)
filename.exe < input.txt > output.txt
• Windows command line prompt
1. First, use "cd" to change the working directory to the output directory.
2. Then,
test.exe < input.txt > output.txt
OTHER HANDY TECHNIQUES
memset( array, -1, sizeof(array) );
• Initialization: clear an array (can be multidimensional) to 0 or -1
#include <cstring>
char vst[102][102];
memset(vst, -1, sizeof(vst));
• Number of test cases: t
while (t--) {
// your solution for each test case here
}
OTHER HANDY TECHNIQUES (CONT.)
• Directional vectors for traversing 2-D surfaces
• int mx[4] = {1, 0, -1, 0};
int my[4] = {0, 1, 0, -1};
• for (int i = 0; i < 4; i++) {
newX = originalX + mx[i];
newY = originalY + my[i];
// do something
} You
(0, 1)
(0, -1)
(-1, 0) (1, 0)
GOOD PRACTICES
• Named constants
Define the paramaters of your program.
For instance, the maximum size of the data to process.
#define MAX 102
int a[MAX];
* Choose a slightly larger number for array sizes
• Unit tests
Divide your program into different parts. Test them individually before
assembling them altogether.
* Always check for boundary conditions
AD HOC
TIME TO BRAINSTORM !
AD HOC
• Some probems are hard to be defined.
• In plenty of cases, the solutions are exclusive to these problems.
• To put it simply, you actually need to be creative (!!) and thoughtful.
• Keys to these problems:
• 1. Problem decomposition / unpacking
• 2. Analyze carefully
CHESS
• Source: German Collegiate Programming Contest (GCPC) 2013
• Online Judge: https://open.kattis.com/problems/chess
• Problem description:
• In chess, bishops can only move diagonal.
Given a 8*8 board and the position of the 2 bishops,
determine
1. whether they can reach each other, and
2. the path if so.
Figure 1: Chessboard, bishop and fields
the bishop can reach in one move
CHESS (INPUT & OUTPUT)
• Input
The input starts with the number of test cases. Each test case consists of one
line, containing the start position X and end position Y. Each position is given
by two space separated characters. A letter for the column and a number for
the row. There are no duplicate test cases in one input.
• Output
Output one line for every test case. If it’s not possible to move a bishop from X
to Y in any number of moves output ’Impossible’. Otherwise output one
possible move sequence from X to Y. Output the number n of moves first
(allowed to be 4 at most). Followed by n+1 positions, which describe the path
the bishop has to go. Every character is separated by one space. There are
many possible solutions. Any with at most 4 moves will be accepted.
CHESS (SOLUTION SKETCHES)
• If we closely observe this problem, It won’t be hard for us to see that, for any
2 positions, only 4 possibilities exist:
• 1. Path length = 0, if 2 positions are the same.
• 2. Path length = 1, if 2 positions are on the same diagonal
• 3. Path length = 2, if the 2 diagonals to which the 2 positions belong intersect
at integer positions (The XY coordinates of which are both integers)
• 4. If above conditions are not satisfied, then the 2 bishops can not reach each
other (impossible).
• Derive the equations of diagonals for both bishops. Then follow the steps
mentioned above.
PACKETS
• Source: ACM Central Europe 1996
• Online Judge: POJ 1017, ZOJ 1307, UVA 311
• Problem description:
• Given packets with 1*1, 2*2, 3*3, 4*4, 5*5, 6*6 in sizes. Fill these packets into
6*6 parcels.
Find out the minimal number of parcels to be used.
PACKETS (中文翻譯)
• 一家工廠生產的產品被包裝在一個正方形的包裝盒中,產品具有相同的
高度h,大小規格為1*1,2*2,3*3,4*4,5*5和6*6。這些產品是用和產
品具有相同高度h,大小規格為6* 6的正方形郵包交付給客戶。因為費用
問題,是工廠和客戶都要最小化將訂購的物品從工廠發送給客戶的郵包
的數量。請您編寫一個程式,對於按照訂單要發送給定的產品,找出最
少的郵包數量,以節省費用。
PACKETS (輸入輸出)
• 輸入:
• 輸入由若干行組成,每行描述一份訂單,每份訂單由6個整數組成,整數
之間用一個空格分開,連續的整數表示從最小的1*1到最大的6*6每種大
小的包裝盒的數量,輸入以包含6個0的一行結束。
• 輸出:
• 對每行輸入,輸出一行,給出郵包的最小數量。對於輸入的最後一行
“空輸入”沒有輸出。
PACKETS (題目解析)
• 這是一道構造法模擬題,其使用的數學模型是一個貪心策略——按照尺寸
遞減的順序裝入包裝盒。由於郵包的尺寸為6*6,因此每個4*4、5*5和
6*6 的包裝盒需要單獨一個郵包。
• 6*6:剛好;
• 5*5:放入6*6 的郵包中 剩下的用1*1填充;
• 4*4:放入6*6的郵包後,先用2*2填充, 沒有2*2的就用1*1填充;
• 3*3:一個6*6的郵包可以放4個;
• 2*2 和 1*1 一樣操作。
PACKETS (題目解析) (CONT.)
• 具體實現方法如下。設i*i的包裝盒數為ai(1≤i≤6):
• 放入6*6、5*5、4*4、3*3的包裝盒至少需要郵包數M=a6+a5+a4+ 。
• M個郵包可填入2*2的包裝盒數L2=a4*5+u[a3 mod 4]∣u[0]=0,u[1]=5,
u[2]=3,u[3]=1。若有剩餘(a2>L2),則放入新增的 個郵包,即
M+= 。
• 最後使用1*1的L1(=m*36-a6*36-a5*25-a4*16-a3*9-a2*4)個包裝盒填滿
M個郵包。若有剩餘(a1>L1),則放入新增的 個郵包,即
M+= 。
• 顯然,M是放入所有包裝盒的最少郵包數。
ENUMERATION
EXPERIENCE THE POWER OF COMPUTERS
ENUMERATION 枚舉
• And ... here we are. Let us experience the power of computers !
• Enumeration: generate possibilities and evaluate them.
• I'm going to give you some examples. <vid> <demo>
FIXED-LENGTH ENUMERATION
Choose your meal : )
How many possibilities are there ?
• 開胃菜:______
• 前菜:______
• 沙拉:______
• 湯:______
• 主餐:______
• 甜點:______
• 飲料:______
NUMBER GUESSING 猜數字
• Source: National Problem Solveing Contest 2007 Junior Final
• Online Judge: ZeroJudge b084
• Problem description:
• Number Guessing is a computer game. First, the computer chooses four
different digits, you need to guess these four digits in the fewest times.
For each guess, the computer will show a judgement in the form of "#A#B",
"#" is a number 0~4. "#A" shows how many digits you guessed with both
correct value and position. "#B" shows how many digits you guessed with
correct value but incorrect position.
• Given the digits you guessed and the judgements you got, can you figure out
how many possible correct answers are there ?
NUMBER GUESSING (中文翻譯)
• 猜數字是一種益智小遊戲,通常是兩個人一起玩,其規則如下:
• 一個人負責出數字,另一個人猜。出數字的人要先想好一個沒有重複數
字的4位數,不能讓猜的人知道。猜的人就可以開始猜。每猜一個數,出
數者就要根據這個數字給出幾A幾B,其中A前面的數字表示位置正確的數
的個數,而B前的數字表示數字正確而位置不對的數的個數。
• 如正確答案為5234,而猜的人猜5346,則是1A2B,其中有一個5的位置對
了,記為1A,而3和4這兩個數字對了,而位置沒對,因此記為2B,合起
來就是1A2B。
• 接著猜的人再根據出題者的幾A幾B繼續猜,直到猜中為止後兩人互換,
用比較少次數猜出數字的人獲勝。
• 今天小偉跟小承打賭玩猜數字,小承猜了幾個數字後就找路過的你幫忙。
NUMBER GUESSING (輸入輸出)
• 輸入:
• 輸入檔中會有多筆資料,第一行是一個正整數k,代表一共有多少組資料,
接下來是k組測試資料,每組測試資料的第一行是一個數字n,n不會超過
10,代表小承已經猜過的次數,接下來有n行,每行分別是一個不重複的
四位數字以及小偉給他的幾A幾B的結果。
• 輸出:
• 對每組測試資料,請輸出一行數字,表示還有多少組數字有可能是小偉
心裡想的數字,如果都沒有請輸出”You Cheat!”
NUMBER GUESSING (題目解析)
• 這算是一題滿經典的題目;有些人一開始可能會朝排列組合思考,但是
這麼想其實是多餘的。
• 考慮一下可能的組合總共有多少,我們會發現只有 10 * 9 * 8 * 7 = 5040 種,
不多,所以在這邊我們可以採用枚舉的方式,把這 5040 種可能都舉出來,
並且一一跟輸入的測試做比對;如果所有測試都符合的話,代表這是一
個可能的答案,將ans++。
• 最後在枚舉結束後,輸出ans,或是You Cheat! (ans == 0的時候)
VARIABLE-LENGTH ENUMERATION
• Sometimes, we face choices with variable depths.
• Sometimes, the choices we make affect one another.
• Or sometimes, there are simply too many choices to make.
• For example
• 1. Dressing up.
• 2. Course selection. How you arrange the courses you take ?
• 3. How do you distribute your monthly budget ?
RECURSIVE ENUMERATION
• In these type of problems, you will find yourself in making similar decisions
again and again, repeatedly.
• A common example is Maze.
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION: PATH FINDING IN MAZE
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0)
(0, 0)
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0)
(0, 0)
(1, 0)
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(0, 0)
(1, 0) (2, 0)
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(1, 0) (2, 0) (3, 0)
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(1, 0) (2, 0) (3, 0)
Cannot
continue
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(1, 0) (2, 0)
Cannot
continue
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(2, 1)
(1, 0) (2, 0) (2, 1)
Cannot
continue
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(2, 1) (2, 2)
(1, 0) (2, 0) (2, 2)(2, 1)
Cannot
continue
RECURSIVE ENUMERATION (CONT.)
• You may look at the process like this
Step1 Step2 Step3 Step4 Step5
(0, 0)
(0, 0) (1, 0) (2, 0)
(3, 0)
(0, 0)
(2, 1) (2, 2)
(1, 0) (2, 0) (2, 2)(2, 1)
Cannot
continue
You're always choosing a new option, essentially
IMPLEMENTATION: RECURSIVE FUNCTIONS
• Let's use the Maze example to demonstrate the idea.
• bool walk(int x, int y)
{
if (map[x][y] == EXIT) { puts("We found the exit!"); return true; }
// if we're not at the exit, we continue walking
for each (nx, ny) next to (x, y)
if (canWalk(nx, ny)) {
bool ret = walk(nx, ny);
if (ret) return true; // found a way in the following steps
}
return false; // unable to find a way
}
OTHER CLASSIC EXAMPLES
• The House Of Santa Claus (UVa.291)
• 8 Queens Chess Problem (UVa. 750)
• Su DoKu (UVa.981)
THE HOUSE OF SANTA CLAUS
• Redraw the following figure (ie. Draw all the edges).
Print out all possibilities.
8-QUEENS CHESS PROBLEM
• Place 8 Queens on the chessboard without any 2 queens placed on the same
row or column.
SU DOKU
• Solve the classic Su DoKu problem.
ADDITIONAL KNOWLEDGE
• Avoid repeated visits
For instance,
(Maze) you don't want to walk to the same spot again.
(Su DoKu) no need to place 4 if the row, column or box already contains 4.
You need additional arrays to store such information.
eg. bool visited[MAZE_HEIGHT][MAZE_WIDTH];
• Backtracking
Record your options along the way.
eg. Maze
step[ currentStep ] = (nx, ny);
walk(nx, ny);
COMBINING ALTOGETHER
• bool visited[MAZE_HEIGHT][MAZE_WIDTH] = { false };
bool walk(int currentStep, int x, int y)
{
if (map[x][y] == EXIT) {
puts("We found the exit!");
for (int i = 0; i < currentStep; i++) printf("%d, ", step[i]);
return true;
}
// if we're not at the exit, we continue walking
for each (nx, ny) next to (x, y)
if (visited[nx][ny] == false && canWalk(nx, ny)) {
visited[nx][ny] = true;
step[ currentStep ] = (nx, ny);
bool ret = walk(currentStep+1, nx, ny);
if (ret) return true; // found a way in the following steps
}
return false; // unable to find a way
}
Essential C/C++
Thank you for listening
Good luck on the afternoon practice : )

More Related Content

PDF
Basic Enumeration (Chinese)
PDF
Python 温故
PDF
Hands on data analysis 101
 
PPTX
Python 入門
PPTX
C語言重要觀念快速複習與基本資料結構之觀念(適合資工電機相關科系,大一程度閱讀)
PPTX
12, string
PPTX
Study4.TW .NET Conf 2018 - Fp in c#
PPTX
02.python基础
Basic Enumeration (Chinese)
Python 温故
Hands on data analysis 101
 
Python 入門
C語言重要觀念快速複習與基本資料結構之觀念(適合資工電機相關科系,大一程度閱讀)
12, string
Study4.TW .NET Conf 2018 - Fp in c#
02.python基础

Similar to Essential C/C++ (20)

PDF
机器学习与深度学习简介.pdf
PDF
RSpec & TDD Tutorial
PDF
看似比較簡單堆推坑教學 C語言崩潰到崩潰(一)
PDF
02_Introduction_to_Python_Programming.pdf
PDF
Mysql开发与优化
PDF
JCConf 2023 - 深入淺出 Java 21 功能
PPTX
C++11综述/新特性描述/Overview of C++11 New Features
PDF
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
PDF
20200323 - AI Intro
PPTX
TypeScript 綜合格鬥技
ODP
Ihome inaction 篇外篇之fp介绍
PDF
淘宝前端优化
PDF
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
PPTX
yzu2017camp - Class
PPTX
R intro 20140716-basic
PDF
[科科營]電腦概述
PDF
PDF
非監督是學習_Kmeans_process_visualization20241110.pdf
 
PDF
Arduino L2
KEY
Ruby basic
机器学习与深度学习简介.pdf
RSpec & TDD Tutorial
看似比較簡單堆推坑教學 C語言崩潰到崩潰(一)
02_Introduction_to_Python_Programming.pdf
Mysql开发与优化
JCConf 2023 - 深入淺出 Java 21 功能
C++11综述/新特性描述/Overview of C++11 New Features
看似比較簡單的推坑教學 C語言從崩潰到崩潰Ex(二)
20200323 - AI Intro
TypeScript 綜合格鬥技
Ihome inaction 篇外篇之fp介绍
淘宝前端优化
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
yzu2017camp - Class
R intro 20140716-basic
[科科營]電腦概述
非監督是學習_Kmeans_process_visualization20241110.pdf
 
Arduino L2
Ruby basic
Ad

Essential C/C++

  • 1. ENHANCE YOUR FUNDAMENTAL SKILLS 2015 NCTU WINTER CAMP :: DAY 2
  • 2. ABOUT THE LECTURER • Name: lnishan. • Undergraduate, NCTU CS 106. • 9 years of competitive programming experience.
  • 3. OUTLINES FOR TODAY'S COURSE • C/C++ Essentials • Brute force & Simulation • Useful techniques • ad hoc • Enumeration
  • 4. C/C++ ESSENTIALS HANDY SYNTAXES AND COMMON PITFALLS
  • 5. BASIC I/O • cin / cout are absurdly slow. • ~10x slower than scanf / printf • For test cases with 10+ MB in size, you would spend an unreasonable amount of time on I/O.
  • 6. SCANF / PRINTF format: a char string with "specifiers" and other characters specifiers: indicate a type of variable Examples • scanf("%d%d", &a, &b); // read 2 integers • printf("%.2f: %.5f", f1, f2); // print 2 floating point numbers: scanf( format, pointer of variable 1, pointer of variable 2, … printf( format, variable 1, variable 2, …
  • 7. SCANF / PRINTF: SPECIFIERS scanf printf int %d long long int %lld * unsigned int %u unsigned long long int %llu * float %f double %lf char string %s int %d long long int %lld * unsigned int %u unsigned long long int %llu * float %f double %f char string %s * On Windows XP: long long int = %I64d, rather than %lld. Common pitfalls • double remains %f in printf() • Do NOT use %c for char
  • 8. DEALING WITH ARBITRARY NUMBER OF ELEMENTS IN A SINGLE LINE • Sometimes, problems (esp. in the old days) love to play tricks with I/O. • Suppose the input says you'll be given arbitrary numbers in a single line. • strtok(): #include <cstring>, atoi(): #include <cstdlib> 1 4 9 4 3 10 15 6 5 14 32 11 Add them up ? • int ans; char *ptr; char s[1000]; while (gets(s)) { ans = 0; ptr = strtok(s, " "); while (ptr != NULL) { ans += atoi(ptr); ptr = strtok(NULL, " "); } printf("%dn", ans); }
  • 9. OTHER STL THAT WOULD HELP YOU WITH I/O sscanf( string, format, pointer of variable 1, pointer of variable 2, … sprintf( string, format, variable 1, variable 2, … sscanf( stringTime, "%d:%d:%d", &h, &m, &s ); • sscanf / sprintf: These 2 are essentially the same as scanf / printf, except the operations are done on the string, rather than stdin / stdout. ssprintf( stringTime, "%d:%d:%d", h, m, s ); scanf(" "); • Get rid of redundant characters (such as newline 'n') in the input buffer.
  • 10. COMMON PITFALL: STACK OVERFLOW • What is "Stack Overflow"? - Exceeded maximum system stack size • Key notes: Do NOT declare big arrays in local scopes • Solutions: 1. Declare arrays in global scope 2. std::vector 3. Dynamic arrays (not recommended)
  • 11. STD::VECTOR • Think of it as a variable-length array. Its size can be altered during run time. • Size is 0 initially. (resize or add elements in before using it) • #include <vector> vector< member type > myVec; myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4] int int int int int ● ● ● • Declaration vector<int> myVec;
  • 12. STD::VECTOR (CONT.) myVec.push_back( element ); myVec myVec[0] myVec[1] myVec[2] 1 2 3 myVec.resize( size ); myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4] 1 2 3 int int • Add an element to the back of the array (vector) myVec.push_back(1); myVec.push_back(2); myVec.push_back(3); • Resize the vector myVec.resize(5);
  • 13. STD::VECTOR (CONT.) myVec myVec[0] myVec[1] myVec[2] myVec[3] myVec[4] 1 2 3 int int myVec.size() myVec.clear(); • Access elements like it's an array. • Get the size of the vector for (int i = 0; i < myVec.size(); i++) printf("%dn", myVec[i]); • Clear the vector myVec.clear();
  • 14. BRUTE FORCE & SIMULATION "HOW DIFFICULT CAN THIS BE?" - ME 2009
  • 15. TOOLS & PRACTICES RECOMMENDED HAVING • Basic OOP: struct, operator overloading • Basic pointer operations • Good naming conventions
  • 16. STRUCT & OPERATOR OVERLOADING • Think of struct as a self-created data type. The data type can contain several member variables and functions. • struct Matrix { int mat[4][4]; Matrix operator + (Matrix &rhs); Matrix operator * (Matrix &rhs); }; • Useful in a lot of conditions
  • 17. CLASSIFICATIONS 分類 • Courtesy of Prof. Yonghui Wu • 1. Descriptive simulation 直敘式模擬 • 2. Screening simulation 篩選法模擬 • 3. Constructive simulation 構造法模擬
  • 18. 直敘式模擬 • 直敘式模擬就是按照題目要求進行模擬。 • 雖然不需要什麼精妙演算法,但程式設計者一定要忠實於原題,認真審 題,千萬不要疏漏任何條件,精心設計方便類比的資料結構。 • “直敘式模擬”的難度取決於類比物件所包含的動態變化的屬性有多少, 動態屬性愈多,則難度愈大。 • 直敘式模擬的形式一般有兩種 • (1) 按指令行事,一般採用命令序列分析法 • (2) 按時間順序模擬,一般採用時間序列分析法
  • 19. THE HARDEST PROBLEM EVER • Source: ACM South Central USA 2002 • Online Judge: POJ 1298、ZOJ 1392、UVA 2540 • Problem description: Decrypt a string by shifting each alphabetical character by -5.
  • 20. THE HARDEST PROBLEM EVER (中文翻譯) • 凱撒大帝(Julius Caesar)生活在充滿了危險和陰謀的年代,他要面臨在最困 難的情況下讓自己生存下來的問題。為了能夠生存,他創建了第一套密碼。 這個密碼聽起來是如此地令人難以置信,以至於沒有人能弄清楚它是如何工 作的。 • 您是凱撒軍隊中的一名下級軍官。您的工作是破譯凱撒發來的郵件,並報告 給您的將軍。凱撒加密的方法很簡單。對於原文中的每一個字母,用這個字 母之後的第五個字母來替換(即,如果原文的字母是“A”,則要替換為密碼 字母“F”)。因為您是要把凱撒的郵件翻譯為原文檔,所以您要做相反的事 情(由將密碼轉換為原文): • 密碼字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z • 原文字母:V W X Y Z A B C D E F G H I J K L M N O P Q R S T U • 在密碼檔中只有字母才被替換,其他的非字母字元保持不變,所有的英文字 母為大寫。
  • 21. THE HARDEST PROBLEM EVER (輸入輸出) • 輸入: 本問題的輸入由多達100個(非空的)測試用例組成。每個測試用例格式 如下描述,在測試用例之間沒有空行分開。所有的字元為大寫。 一個測試用例由3部分組成: 起始行 —— 一行,“START” 密碼消息 —— 一行,由100到200個字元組成,包含100和200,表示由凱 撒發送來的一條消息。 結束行 —— 一行,“END” 在最後一個測試用例後,給出一行,“ENDOFINPUT”。 • 輸出: 對每個測試用例,輸出一行,給出凱撒的原始資訊。
  • 22. THE HARDEST PROBLEM EVER (題目解析) • 按指令行事的簡單直敘式模擬題。按照加密規則,26個大寫英文字母依 序圍成一圈,密碼字母逆時針方向上的第5個字母即為原文字母,即 • 原文字母 = 'A'+(密碼字母- 'A'+21)% 26 • 按照上述規則,依次解密密碼檔中的大寫字母,即可得到原文。
  • 23. SPEED LIMIT • Source: ACM Mid-Central USA 2004 • Online Judge: POJ 2017, ZOJ 2176, UVA 3059 • Problem description: • Given the speed of Bill and Ted in different time periods, calculate the total distance driven
  • 24. SPEED LIMIT (中文翻譯) • Bill和Ted踏上行程,但他們汽車的里程表壞了,因此他們不知道他們駕車 走了多少英里。幸運的是,Bill有一個正在運行的跑錶,因此他們可以記 錄他們的速度和駕駛了多少時間。然而,這個跑錶記錄的方式有些古怪, 因此他們需要計算總的駕駛距離。請你編寫一個程式完成這項計算。 • 例如,他們的跑錶顯示如下: 每小時速度 (英里) 總共經歷時間 (小時) 20 2 30 6 10 7 • 這表示開始的2小時他們以20英里的時速行駛,然後的6-2=4小時他們以30 英里的時速行駛,再以後的7-6=1小時他們以10英里的時速行駛,所以行 駛的距離是(2)(20) + (4)(30) + (1)(10) = 40+120+10=170英里。總的時間耗費 是從他們旅行開始進行計算,而不是從跑錶開始計數開始計算。
  • 25. SPEED LIMIT (輸入輸出) • 輸入: • 輸入由一個或多個資料集合組成。每個資料集合開始的第一行為一個整 數n,1≤n≤10;後面是n對值,每對一行。每對的第一個值s是時速,第二 個值t是總的耗費時間。s和t都是整數,1 ≤s≤90並且1≤t≤12。t的值總是增 序。n的值取-1表示輸入結束。 • 輸出: • 對於每一個資料集合,輸出行駛距離,然後空格,輸出單詞"miles"。
  • 26. SPEED LIMIT (題目解析) • 本題是一道十分簡單的直敘式模擬題,計算過程就是模擬跑錶的運行來 計算總里程:若上一個記錄的駕駛時間為lt,目前記錄的速度為s、駕駛 時間為t,則當前跑的距離為(t - lt) *s ,將該距離累計入總里程。
  • 27. RIDE TO SCHOOL • Source: ACM Beijing 2004 Preliminary • Online Judge: POJ 1922, ZOJ 2229 • Problem description: • Students ride bikes from Wanliu to Yanyuan starting at different time with different but fixed speeds. Charley however, ride bikes in an unusual way. He stays still initially. Once being surpassed, he would speed up to follow that surpasser. • Find out when Charley reaches Yanguan given all the info mentioned above.
  • 28. RIDE TO SCHOOL (中文翻譯) • 北京大學的許多研究生住在萬柳校區,距離主校區燕園校區有4.5公里。 住在萬柳的同學或者乘坐巴士,或者騎自行車去主校區上課。由於北京 糟糕的交通,許多同學選擇騎自行車。 • 我們假定除了Charley以外,所有的同學從萬柳到燕園都是以某一個確定 的速度騎自行車。Charley則有一個不同的騎車習慣——他總是要跟在另一 個騎車同學的後面,以免一個人獨自騎車。當Charley到萬柳校區的大門 口的時候,他就等待離開萬柳去燕園的同學。如果他等到這樣的同學, 他就騎車跟著這位同學;如果沒有這樣的同學,他就等待去燕園的同學 出現,然後騎車跟上。在從萬柳到燕園的路上,如果有騎得更快的同學 超過了Charley,他就離開原先他跟著的同學,加速跟上騎得更快的同學。 • 假設Charley到萬柳校區的大門口的時間為0,給出其他同學離開萬柳的時 間和速度,請你給出Charley到達燕園的時間。
  • 29. RIDE TO SCHOOL (輸入輸出) • 輸入: • 有幾組測試用例,每組測試用例的第一行為N (1 ≤ N ≤ 10000),表示除了 Charley外,騎車同學的數量。以N=0表示輸入結束。每組測試用例的第一 行後面的N行表示N個騎車同學的資訊,形式為 • Vi [空格] Ti • Vi 是一個正整數≤ 40,表示第i個騎車同學的速度(kph,每小時公里數), Ti 則是第i個騎車同學離開萬柳的時間,是一個整數,以秒為單位。在任 何測試用例中總存在非負的Ti。 • 輸出: • 對每個測試用例輸出一行:Charley到達的時間。在處理分數的時候進1。
  • 30. RIDE TO SCHOOL (SOLUTION THOUGHT PROCESS) • You could just simulate accordingly, but … • Take a second look. • Imagine yourself as Charley (Hi Charley !), you're currently riding the bike at some speed. When you get surpassed (note that this only happens during the way), you would follow that rider who surpassed you. This essentially turns you into that rider. Repeat this thought process again when you get surpassed by another rider. You will realize, in the end, you will become the earliest rider to arrive at Yanyuan. • The problem becomes easy once you've realized this, but note that there is a pitfall: Only consider the riders who start later than you. (ie. ignore riders who start at negative seconds)
  • 31. RIDE TO SCHOOL (題目解析) • 本題沒有數學公式和規律,通過直譯模擬每個同學去往燕園校區的情景, 得出Charley從萬柳校區到燕園校區的時間。所以對每組測試資料,從 Charley到萬柳校區的大門的時間0開始計時,求出每個同學到達燕園校區 所用的時間,最少的時間就是Charley從萬柳校區的大門到燕園校區的時 間。 • 設前i-1同學中最早到達燕園校區的時間為min;第i個同學的車速為v,離 開萬柳校區的時間為t,即該同學到達燕園校區的時間x=t+ 4.5*3600/v。 若x<min,則調整min為x。顯然,按照這一方法依次計算所有同學的到達 時間,最後得出的min即為Charley到達的時間。
  • 32. 篩選法模擬 • 模擬過程中可能產生的所有解組成一個篩。 篩選法模擬即先從題意中找出約束條件,然 後將篩中的每一個可能解放到約束條件的篩 檢程式上,一次一次地將不符合條件的解過 濾掉,最後沉澱在篩中的即為問題的解。 • (編按) 白話點講就是,題目對於答案可能有 很多條件必須要逐一檢查;如果過程中全部 條件都符合的話,那這就是一組可行的解答。 好餐廳? 食物好吃? 氣氛佳? 服務親切? 摁 ! 是間好餐廳 !
  • 33. LOGICAL ERRORS • 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (? • 1. 如果味道好吃,我就說這是美食 • 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食 • 判斷餿食?
  • 34. LOGICAL ERRORS • 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (? • 1. 如果味道好吃,我就說這是美食 • 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食 • 判斷餿食? if (味道難吃 || 聞起來很臭) 這道菜 = 餿食;
  • 35. LOGICAL ERRORS • 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (? • 1. 如果味道好吃,我就說這是美食 • 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食 • 判斷餿食? 如果味道好吃、但聞起來很臭呢 ? if (味道難吃 || 聞起來很臭) 這道菜 = 餿食;
  • 36. LOGICAL ERRORS • 假設我用這樣的邏輯去判斷一道菜是美食還是餿食 (? • 1. 如果味道好吃,我就說這是美食 • 2. 如果味道難吃,或是聞起來很臭,我就說這是餿食 • 判斷餿食? 如果味道好吃、但聞起來很臭呢 ? if (味道難吃 || (味道難吃 && 聞起來很臭)) if (味道難吃 || 聞起來很臭) 這道菜 = 餿食;
  • 37. THE GAME • Source: ACM Tehran Sharif 2004 Preliminary • Online Judge: POJ 1970, ZOJ 2495 • Problem description: Given a Connect5 board. Determine the state.
  • 38. THE GAME (中文翻譯) • 五子棋遊戲是由兩名玩家在一個19*19的棋盤上玩的遊戲。一名玩家執黑, 另一名玩家執白。遊戲開始時棋盤為空,兩名玩家交替放置黑色棋子和 白色棋子。執黑者先走。棋盤上有19條水平線和19條垂直線,棋子放置 在直線的交點上。 • 水平線從上到下標記為1,2,...,19,垂直線從左至右標記為1,2,..., 19。 • 這一遊戲的目標是把5個相同顏色的棋子沿水準,垂直或對角線連續放置。 所以,在圖中執黑的一方獲勝。但是,如果一個玩家將超過五個相同顏 色的棋子連續放置,也不能判贏。 • 基於這一遊戲的棋盤情況,請您寫一個程式,確定是白方贏了比賽,還 是黑方贏了比賽,或者是還沒有一方贏了比賽。輸入資料保證不可能出 現黑方和白方都贏的情況,也沒有白方或黑方在多處獲勝的情況。
  • 39. THE GAME (輸入輸出) • 輸入: • 輸入的第一行包含一個整數t (1≤t≤11),表示測試用例的數目。接下來給 出每個測試用例,每個測試用例19行,每行19個數,黑棋子標識為1,白 棋子標識為2,沒有放置棋子則標識為0。 • 輸出: • 對每個測試用例,輸出一行或兩行。在測試用例的第一行輸出結果,如 果黑方獲勝,則輸出1;如果白方獲勝,則輸出2;如果沒有一方能獲勝, 則輸出0。如果黑方或白方獲勝,則在第二行給出在5個連續的棋子中最 左邊的棋子水平線編號和垂直線編號(如果5枚連續的棋子垂直排列,則 選最上方棋子的水平線編號和垂直線編號)。
  • 40. THE GAME (題目解析) • 初始時所有棋子組成一個篩子。我們由上而下、由左而右掃描每個棋子,分 析其k方向的相鄰棋子(0≤k≤3,0≤i,j≤18,見圖): 篩檢程式中“贏”的約束條件是 • (i,j)k的相反方向的相鄰格(x,y)不同色; • (i,j)k方向延伸5格在界內; • 從(i,j)開始,沿k方向連續5格同色且第6格不同色; 若(i,j)的棋子滿足上述約束條件,其顏色所代表的一方贏,(i,j)即為贏方 5個連續的同色棋子中首枚棋子的位置;若檢測了4個方向,(i,j)的棋子依然 不滿足約束條件,則被過濾掉。 若過濾了篩中的所有棋子後篩子變空,則說明沒有一方能獲勝。
  • 42. PACKETS • Source: ACM Central Europe 1996 • Online Judge: POJ 1017, ZOJ 1307, UVA 311 • Problem description: • Given packets with 1*1, 2*2, 3*3, 4*4, 5*5, 6*6 in sizes. Fill these packets into 6*6 parcels. Find out the minimal number of parcels to be used. • --- We'll come back to this later
  • 44. DEBUGGING: MAKE USE OF THE DEBUGGER • A lot of IDEs offer debugger with GUI. Try make the best use of it. • - Breakpoints • - Next Line Code::Blocks 13.12
  • 45. DEBUGGING: FILE I/O USING STDIN/STDOUT • File I/O is sometimes useful for debugging in certain circumstances, say you have a large project or a program that would print out lots of information. • In such situations, you won't want to modify all the scanf/printf s. • There are 2 ways that allow you to use File I/O without changing your code. • 1. freopen() • 2. Windows command line (CMD)
  • 46. DEBUGGING: FILE I/O USING STDIN/STDOUT (CONT.) freopen( input_filename, "r", stdin); freopen( output_filename, "r", stdin); Add these lines of code in the beginning. freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
  • 47. DEBUGGING: FILE I/O USING STDIN/STDOUT (CONT.) filename.exe < input.txt > output.txt • Windows command line prompt 1. First, use "cd" to change the working directory to the output directory. 2. Then, test.exe < input.txt > output.txt
  • 48. OTHER HANDY TECHNIQUES memset( array, -1, sizeof(array) ); • Initialization: clear an array (can be multidimensional) to 0 or -1 #include <cstring> char vst[102][102]; memset(vst, -1, sizeof(vst)); • Number of test cases: t while (t--) { // your solution for each test case here }
  • 49. OTHER HANDY TECHNIQUES (CONT.) • Directional vectors for traversing 2-D surfaces • int mx[4] = {1, 0, -1, 0}; int my[4] = {0, 1, 0, -1}; • for (int i = 0; i < 4; i++) { newX = originalX + mx[i]; newY = originalY + my[i]; // do something } You (0, 1) (0, -1) (-1, 0) (1, 0)
  • 50. GOOD PRACTICES • Named constants Define the paramaters of your program. For instance, the maximum size of the data to process. #define MAX 102 int a[MAX]; * Choose a slightly larger number for array sizes • Unit tests Divide your program into different parts. Test them individually before assembling them altogether. * Always check for boundary conditions
  • 51. AD HOC TIME TO BRAINSTORM !
  • 52. AD HOC • Some probems are hard to be defined. • In plenty of cases, the solutions are exclusive to these problems. • To put it simply, you actually need to be creative (!!) and thoughtful. • Keys to these problems: • 1. Problem decomposition / unpacking • 2. Analyze carefully
  • 53. CHESS • Source: German Collegiate Programming Contest (GCPC) 2013 • Online Judge: https://open.kattis.com/problems/chess • Problem description: • In chess, bishops can only move diagonal. Given a 8*8 board and the position of the 2 bishops, determine 1. whether they can reach each other, and 2. the path if so. Figure 1: Chessboard, bishop and fields the bishop can reach in one move
  • 54. CHESS (INPUT & OUTPUT) • Input The input starts with the number of test cases. Each test case consists of one line, containing the start position X and end position Y. Each position is given by two space separated characters. A letter for the column and a number for the row. There are no duplicate test cases in one input. • Output Output one line for every test case. If it’s not possible to move a bishop from X to Y in any number of moves output ’Impossible’. Otherwise output one possible move sequence from X to Y. Output the number n of moves first (allowed to be 4 at most). Followed by n+1 positions, which describe the path the bishop has to go. Every character is separated by one space. There are many possible solutions. Any with at most 4 moves will be accepted.
  • 55. CHESS (SOLUTION SKETCHES) • If we closely observe this problem, It won’t be hard for us to see that, for any 2 positions, only 4 possibilities exist: • 1. Path length = 0, if 2 positions are the same. • 2. Path length = 1, if 2 positions are on the same diagonal • 3. Path length = 2, if the 2 diagonals to which the 2 positions belong intersect at integer positions (The XY coordinates of which are both integers) • 4. If above conditions are not satisfied, then the 2 bishops can not reach each other (impossible). • Derive the equations of diagonals for both bishops. Then follow the steps mentioned above.
  • 56. PACKETS • Source: ACM Central Europe 1996 • Online Judge: POJ 1017, ZOJ 1307, UVA 311 • Problem description: • Given packets with 1*1, 2*2, 3*3, 4*4, 5*5, 6*6 in sizes. Fill these packets into 6*6 parcels. Find out the minimal number of parcels to be used.
  • 57. PACKETS (中文翻譯) • 一家工廠生產的產品被包裝在一個正方形的包裝盒中,產品具有相同的 高度h,大小規格為1*1,2*2,3*3,4*4,5*5和6*6。這些產品是用和產 品具有相同高度h,大小規格為6* 6的正方形郵包交付給客戶。因為費用 問題,是工廠和客戶都要最小化將訂購的物品從工廠發送給客戶的郵包 的數量。請您編寫一個程式,對於按照訂單要發送給定的產品,找出最 少的郵包數量,以節省費用。
  • 58. PACKETS (輸入輸出) • 輸入: • 輸入由若干行組成,每行描述一份訂單,每份訂單由6個整數組成,整數 之間用一個空格分開,連續的整數表示從最小的1*1到最大的6*6每種大 小的包裝盒的數量,輸入以包含6個0的一行結束。 • 輸出: • 對每行輸入,輸出一行,給出郵包的最小數量。對於輸入的最後一行 “空輸入”沒有輸出。
  • 59. PACKETS (題目解析) • 這是一道構造法模擬題,其使用的數學模型是一個貪心策略——按照尺寸 遞減的順序裝入包裝盒。由於郵包的尺寸為6*6,因此每個4*4、5*5和 6*6 的包裝盒需要單獨一個郵包。 • 6*6:剛好; • 5*5:放入6*6 的郵包中 剩下的用1*1填充; • 4*4:放入6*6的郵包後,先用2*2填充, 沒有2*2的就用1*1填充; • 3*3:一個6*6的郵包可以放4個; • 2*2 和 1*1 一樣操作。
  • 60. PACKETS (題目解析) (CONT.) • 具體實現方法如下。設i*i的包裝盒數為ai(1≤i≤6): • 放入6*6、5*5、4*4、3*3的包裝盒至少需要郵包數M=a6+a5+a4+ 。 • M個郵包可填入2*2的包裝盒數L2=a4*5+u[a3 mod 4]∣u[0]=0,u[1]=5, u[2]=3,u[3]=1。若有剩餘(a2>L2),則放入新增的 個郵包,即 M+= 。 • 最後使用1*1的L1(=m*36-a6*36-a5*25-a4*16-a3*9-a2*4)個包裝盒填滿 M個郵包。若有剩餘(a1>L1),則放入新增的 個郵包,即 M+= 。 • 顯然,M是放入所有包裝盒的最少郵包數。
  • 62. ENUMERATION 枚舉 • And ... here we are. Let us experience the power of computers ! • Enumeration: generate possibilities and evaluate them. • I'm going to give you some examples. <vid> <demo>
  • 63. FIXED-LENGTH ENUMERATION Choose your meal : ) How many possibilities are there ? • 開胃菜:______ • 前菜:______ • 沙拉:______ • 湯:______ • 主餐:______ • 甜點:______ • 飲料:______
  • 64. NUMBER GUESSING 猜數字 • Source: National Problem Solveing Contest 2007 Junior Final • Online Judge: ZeroJudge b084 • Problem description: • Number Guessing is a computer game. First, the computer chooses four different digits, you need to guess these four digits in the fewest times. For each guess, the computer will show a judgement in the form of "#A#B", "#" is a number 0~4. "#A" shows how many digits you guessed with both correct value and position. "#B" shows how many digits you guessed with correct value but incorrect position. • Given the digits you guessed and the judgements you got, can you figure out how many possible correct answers are there ?
  • 65. NUMBER GUESSING (中文翻譯) • 猜數字是一種益智小遊戲,通常是兩個人一起玩,其規則如下: • 一個人負責出數字,另一個人猜。出數字的人要先想好一個沒有重複數 字的4位數,不能讓猜的人知道。猜的人就可以開始猜。每猜一個數,出 數者就要根據這個數字給出幾A幾B,其中A前面的數字表示位置正確的數 的個數,而B前的數字表示數字正確而位置不對的數的個數。 • 如正確答案為5234,而猜的人猜5346,則是1A2B,其中有一個5的位置對 了,記為1A,而3和4這兩個數字對了,而位置沒對,因此記為2B,合起 來就是1A2B。 • 接著猜的人再根據出題者的幾A幾B繼續猜,直到猜中為止後兩人互換, 用比較少次數猜出數字的人獲勝。 • 今天小偉跟小承打賭玩猜數字,小承猜了幾個數字後就找路過的你幫忙。
  • 66. NUMBER GUESSING (輸入輸出) • 輸入: • 輸入檔中會有多筆資料,第一行是一個正整數k,代表一共有多少組資料, 接下來是k組測試資料,每組測試資料的第一行是一個數字n,n不會超過 10,代表小承已經猜過的次數,接下來有n行,每行分別是一個不重複的 四位數字以及小偉給他的幾A幾B的結果。 • 輸出: • 對每組測試資料,請輸出一行數字,表示還有多少組數字有可能是小偉 心裡想的數字,如果都沒有請輸出”You Cheat!”
  • 67. NUMBER GUESSING (題目解析) • 這算是一題滿經典的題目;有些人一開始可能會朝排列組合思考,但是 這麼想其實是多餘的。 • 考慮一下可能的組合總共有多少,我們會發現只有 10 * 9 * 8 * 7 = 5040 種, 不多,所以在這邊我們可以採用枚舉的方式,把這 5040 種可能都舉出來, 並且一一跟輸入的測試做比對;如果所有測試都符合的話,代表這是一 個可能的答案,將ans++。 • 最後在枚舉結束後,輸出ans,或是You Cheat! (ans == 0的時候)
  • 68. VARIABLE-LENGTH ENUMERATION • Sometimes, we face choices with variable depths. • Sometimes, the choices we make affect one another. • Or sometimes, there are simply too many choices to make. • For example • 1. Dressing up. • 2. Course selection. How you arrange the courses you take ? • 3. How do you distribute your monthly budget ?
  • 69. RECURSIVE ENUMERATION • In these type of problems, you will find yourself in making similar decisions again and again, repeatedly. • A common example is Maze.
  • 70. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 71. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 72. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 73. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 74. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 75. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 76. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 77. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 78. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 79. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 80. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 81. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 82. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 83. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 84. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 85. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 86. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 87. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 88. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 89. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 90. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 91. RECURSIVE ENUMERATION: PATH FINDING IN MAZE
  • 92. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (0, 0)
  • 93. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (0, 0) (1, 0)
  • 94. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (0, 0) (1, 0) (2, 0)
  • 95. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (1, 0) (2, 0) (3, 0)
  • 96. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (1, 0) (2, 0) (3, 0) Cannot continue
  • 97. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (1, 0) (2, 0) Cannot continue
  • 98. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (2, 1) (1, 0) (2, 0) (2, 1) Cannot continue
  • 99. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (2, 1) (2, 2) (1, 0) (2, 0) (2, 2)(2, 1) Cannot continue
  • 100. RECURSIVE ENUMERATION (CONT.) • You may look at the process like this Step1 Step2 Step3 Step4 Step5 (0, 0) (0, 0) (1, 0) (2, 0) (3, 0) (0, 0) (2, 1) (2, 2) (1, 0) (2, 0) (2, 2)(2, 1) Cannot continue You're always choosing a new option, essentially
  • 101. IMPLEMENTATION: RECURSIVE FUNCTIONS • Let's use the Maze example to demonstrate the idea. • bool walk(int x, int y) { if (map[x][y] == EXIT) { puts("We found the exit!"); return true; } // if we're not at the exit, we continue walking for each (nx, ny) next to (x, y) if (canWalk(nx, ny)) { bool ret = walk(nx, ny); if (ret) return true; // found a way in the following steps } return false; // unable to find a way }
  • 102. OTHER CLASSIC EXAMPLES • The House Of Santa Claus (UVa.291) • 8 Queens Chess Problem (UVa. 750) • Su DoKu (UVa.981)
  • 103. THE HOUSE OF SANTA CLAUS • Redraw the following figure (ie. Draw all the edges). Print out all possibilities.
  • 104. 8-QUEENS CHESS PROBLEM • Place 8 Queens on the chessboard without any 2 queens placed on the same row or column.
  • 105. SU DOKU • Solve the classic Su DoKu problem.
  • 106. ADDITIONAL KNOWLEDGE • Avoid repeated visits For instance, (Maze) you don't want to walk to the same spot again. (Su DoKu) no need to place 4 if the row, column or box already contains 4. You need additional arrays to store such information. eg. bool visited[MAZE_HEIGHT][MAZE_WIDTH]; • Backtracking Record your options along the way. eg. Maze step[ currentStep ] = (nx, ny); walk(nx, ny);
  • 107. COMBINING ALTOGETHER • bool visited[MAZE_HEIGHT][MAZE_WIDTH] = { false }; bool walk(int currentStep, int x, int y) { if (map[x][y] == EXIT) { puts("We found the exit!"); for (int i = 0; i < currentStep; i++) printf("%d, ", step[i]); return true; } // if we're not at the exit, we continue walking for each (nx, ny) next to (x, y) if (visited[nx][ny] == false && canWalk(nx, ny)) { visited[nx][ny] = true; step[ currentStep ] = (nx, ny); bool ret = walk(currentStep+1, nx, ny); if (ret) return true; // found a way in the following steps } return false; // unable to find a way }
  • 109. Thank you for listening Good luck on the afternoon practice : )