題目分析:
一、數字統計
此題,曾經在某oj上看到過原題。要求和實現都非常簡單。無非是,列舉出所有在範圍內的數字,然後對數字進行拆分,對每一位數字進行判斷。
乙個樸素的for迴圈,巢狀乙個while迴圈,就可以解決這道題目。
下面是程式的核心部分:
for ( i = l ; i <= r ; i++ )
t = i;
while (t > 0)
y = t % 10;
if (y == 2) s++;
t /= 10;
此題丟分,絕對可以認為是絕不應該出現的事情。往參賽選手能夠更加注意自己的程式細節,避免問題出現。
二、接水問題
問題描述隱晦,引導學生朝著純列舉的思想前進,部分用秒列舉的學生會導致嚴重超時。但題目的核心思想卻應該是模擬問題發生的本質順序。也就是,每個新加入的人去接水的位置,一定是當前數列中和最小的那列。所以實現的方法,就是每個新數字,進入前,找出當前序列中最小的位置,加入進去。直到所有的數字都加入進去後結束。最終從所有的數字中,找出最大的那個值,即為所求。
但是,其實有更合適的模型——插入法排序。
即從大到小排序後,無非就是把數字加入到最後乙個數值之上,然後運用插入法排序原理,把這個新數插入到合適位置。最終輸出的是陣列的最大值即可。
下面是程式的核心部分:
首先,對前m個數進行排序,然後後面的n – m個數,就需要模擬插入了:
for (i = m ; i < n ; i++ )
cin >> t;
t += a[m - 1];
j = m - 1;
while (j > 0 && a[j - 1] < t)
a[j] = a[j - 1];
j--;
a[j] = t;
最後a[0]一定是最大值。
非常想用這道題,告訴那些忽視插入法排序的學生,當你寫不好快排的時候,插入法,幫我們解決了很多為了乙個數值而要排全部數值的問題。雖然效率和選擇、冒泡一樣,但插入法確實有它特殊之處。
三、飛彈攔截
再次見到飛彈攔截,頗感親切,但是這次的飛彈攔截,加入了立體環節,也從借用原題概念,讓乙個不存在的動態規劃方法,影響解題思路。
其實,題目的核心解題思想還是貪心和列舉。只不過要列舉的有些策略而已。我也曾試過了,用單位長度去列舉兩個點的半徑,結果殘酷的只過了兩個點。還是經過學生的解釋,明白了排序後的貪心策略。所以,向學生學習,也是老師的必修課程。我再次強調,我經常向學生學習,教學相長,不外乎如此。所以,希望更多的老師,能夠時常放下自己的架子和身份,多多向學生請教,我們共同的成長。
按照到第乙個點的距離平方排序之後,就可以不斷讓最遠的點,不用離開第一點半徑,進入第二點半徑。在這個過程中,第一點半徑逐漸縮小,第二點半徑,可能發生增大。就需要一步步統計出,兩個半徑平方的最小值。最終達到題目要求。
因為考慮到點的數量是100000,所以,無比需要使用快速排序。題目如果想寫的較為簡潔,還是使用結構體比較方便。
首先定義乙個結構體,包括x,y,jr1(距離第1點半徑平方),jr2(距離第2點半徑平方)。
struct dian
int x;
int y;
int j1r;
int j2r;
}d[100050];
這裡面順便定義了乙個10萬數量級的陣列。
快速排序的函式:
void qsort(int s, int e)
dian t;
int l, r;
if (s >= e) return ;
l = s;
r = e;
t = d[s];
while (l < r)
while (l < r && d[r].j1r >= t.j1r) r--;
d[l] = d[r];
while (l < r && d[l].j1r <= t.j1r) l++;
d[r] = d[l];
d[r] = t;
qsort(s, r - 1);
qsort(r + 1, e);
然後就是逐漸退出和更新半徑的過程了:
r = d[n].j1r;
m2 = 0;
for (i = n ; i >= 1 ; i--)
if (d[i].j2r > m2) m2 = d[i].j2r;
tr = d[i - 1].j1r + m2;
if ( r > tr ) r = tr;
最後r即為最小消耗。
四、三國遊戲
從思想實現來說,還是一道列舉加貪心的題目。因為,「人」在和計算機鬥爭的過程中,雙方都無法取得最大的默契配合值。所以,「人」只能夠去考慮次大最優值,但是,為了能夠騙過計算機,我們選擇的,只能夠是跟我們選擇的第一位武將配合值次大的那位武將(如果不是乙個的話也會被計算機破壞掉)。所以,就要求我們必須,找到,每行中次大值最大的那個值(挺擾人的)。當然,這個提法是建立在我們有了題目中展示的那個矩陣之後。你要注意,題目給你的值是這個矩陣的右半邊,你需要把左半邊的值自己不上,才能夠按照行去列舉(當然,做完後,如果你想按照列,也沒有關係,因為全都是對稱的,對吧)。
當然,可能有同學考慮到了0的難問題。很遺憾,這道題肯定不會出現零。因為,計算機只能破壞「人」,而且,我也想到了騙他的方法,計算機必輸無疑。
下面看一下程式的核心部分:
輸入部分:
for (i = 1 ; i < n ; i++)
for (j = i + 1 ; j <= n ; j++ )
cin >> s[i][j];
對稱複製部分:
for (i = 2 ; i <= n ; i++)
for (j = 1 ; j < i ; j++)
s[i][j] = s[j][i];
找每行次大值中的最大值部分:
for (i = 1 ; i <= n ; i++)
t1 = t2 = 0;
for (j = 1 ; j <= n ; j++)
if (s[i][j] > t1) t1 = s[i][j];
if (t1 > t2) swap(t1, t2);
if (t < t1) t = t1;
很明顯,t為每行次大值(t1)的最大值。也就是我們的所求。
本題,最重要的是想到解決的方法,一旦方法確定,程式實現,相當簡單。也望各位選手能夠逐漸提高自己的思維方式。讓自己的能力逐漸提公升。
NOIP 2010 普及組解題報告
題目分析 一 數字統計 此題,曾經在某oj上看到過原題。要求和實現都非常簡單。無非是,列舉出所有在範圍內的數字,然後對數字進行拆分,對每一位數字進行判斷。乙個樸素的for迴圈,巢狀乙個while迴圈,就可以解決這道題目。下面是程式的核心部分 for i l i r i 此題丟分,絕對可以認為是絕不應...
NOIP2010解題報告
t1 機器翻譯 t2 烏龜棋 t3 關押罪犯 t4 引水入城 題解 一套不算太難的noip題目。第一題直接暴力模擬佇列的工作即可。include include include include include include using namespace std intq 10100 int in...
NOIP2010提高組 關押罪犯 解題報告
解題思路 根據題目描述要將n名罪犯分在2座監獄中,可以考慮用二分圖來解答問題,將每名罪犯看為乙個點,存在仇恨的罪犯間連一條無向邊。要使發生衝突的影響力最小,這裡給出兩種解答方法,方法一 運用一點貪心的思想,讓衝突小的發生來使得衝突大的不發生,即將邊按權值由小到大進行排序,刪除當前權值最小的邊,判斷所...