NOIP 2010 普及組解題報告

2022-08-05 06:24:10 字數 3152 閱讀 9622

題目分析:

一、數字統計

此題,曾經在某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座監獄中,可以考慮用二分圖來解答問題,將每名罪犯看為乙個點,存在仇恨的罪犯間連一條無向邊。要使發生衝突的影響力最小,這裡給出兩種解答方法,方法一 運用一點貪心的思想,讓衝突小的發生來使得衝突大的不發生,即將邊按權值由小到大進行排序,刪除當前權值最小的邊,判斷所...