1. 程式人生 > >2017年8月14日套題記錄 | 普及組

2017年8月14日套題記錄 | 普及組

現在 增強 問題 相同 要求 使用 計劃 今天 size

寫在前面

今天登洛谷發現離Noip剩下88天了??(雖然看起有點久),然後覺得似乎水了一個暑假什麽也沒做(雖然學了點數據結構和一些奇奇Gaygay的東西),於是打開題庫發現去年Long Happy的集訓套題我似乎沒有提交過,那就一天一套題,順便碼個題解+心得(霧?


T2.傳作業

題目描述

某十三同學一日上學遲到,此時已經開始上早自習了,所以他只好請同學幫忙把作業傳到組長那裏。由於剛開學不久,某十三同學還沒來得及認識所有同學,所以傳作業時只好找熟悉的同學。已知某十三與組長之間有N個他熟悉的同學,並且知道這些同學相互之間間隔的距離。因為每兩個同學間傳作業都需要下位,所以現在請你幫忙設計一種傳作業的方案,使所有同學下位走動的總距離最小.

輸入格式

第1行,為一個正整數N(N<=98),表示某十三與組長之間的他所熟悉的同學人數。

接下來N+2行,每行有N+2個正整數(integer),其中第I行的第J個數代表第I個同學與第J個同學之間的距離(第1個為某十三本人,第2到第N+1個依次為某十三熟悉的同學,第N+2個是組長)。

輸出格式

輸出包括一行,為一個正整數L,代表最短的總移動距離。

樣例輸入

3
0 3 4 5 1
3 0 6 7 8
4 6 0 7 6
5 7 7 0 4
1 8 6 4 0

樣例輸出

1

解題思路

    • 題意大概是要求從點1(十三同學位置)到點N+2(組長位置)的最短路徑
    • 所以就是一個裸的求最短路的問題
    • 鑒於N的範圍<=98,所以只需使用Floyd就能AC了(當然我不會阻止你打其他的2333

關於代碼

技術分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <iostream>
 6  
 7 using namespace std;
 8  
 9 int Map[101][101];
10  
11 int main(){
12     
13     ios::sync_with_stdio(0
); 14 int n; 15 cin >> n; 16 for (int i = 1;i <= n+2;++i) 17 for (int j = 1;j <= n+2;++j) 18 cin >> Map[i][j]; 19 20 for (int k = 1;k <= n;++k) 21 for (int i = 1;i <= n+2;++i) 22 for (int j = 1;j <= n+2;++j) 23 Map[i][j] = min(Map[i][j] , Map[i][k]+Map[k][j]); 24 25 cout << Map[1][n+2]; 26 return 0; 27 }
傳作業



T4.牛跳

題目描述

John的奶牛們計劃要跳到月亮上去。它們請魔法師配制了P(1 <= P <=150,000)種藥水,這些藥水必需安原來的先後次序使用,但中間可以跳過一些藥水不吃。每種藥水有一個“強度”值 s ( 1 <= s <= 500 ),表示可以增強牛的跳躍能力。然而,藥力的作用卻是交替相反方向起作用,也就是說:當第奇數次吃藥時,牛獲得跳的更高的能力,而第偶數吃藥時,卻降低了跳高能力。在吃藥前,牛的跳高能力當然為 0 。

每種藥只能吃一次,開始時為第1次吃藥。

請求出牛可能跳到的最高高度--最大跳躍能力。

輸入格式

第一行:一個整數 P

下面P行:每行一個整數,表示按先後次序要吃的藥水的“強度”。

輸出格式

只一個整數,表示最大彈跳能力。

樣例輸入

8
7
2
1
8
4
3
5
6

樣例輸出e

17

解題思路

    • 又是動歸
    • 作為動歸段版型選手看了半天選擇了看題解(:看來要加練動歸了,然鵝我看了題解半天才懂pu
    • 設f[i][j]表示前i個藥水中選擇了奇偶性為j的個數的藥的最大跳躍值。 0和1分別表示偶數和奇數
    • 則我們對於第i個藥水的決策,有選/不選兩個決策
    • 若我們選擇了這個藥水i,則對於前i個藥水,我們的奇偶性不同,若不選,則對於前i個藥水奇偶性相同
    • 首先我們先處理邊界條件:
      •   f[1][0] = 0    //不選擇第一個藥水
      • f[1][1] = a[1] //選擇第一個藥水
    • 另我們對於當前第i個藥水的決策有:
      •   偶數選: f[i][0] = f[i-1][1]-a[i] //i-1次為1(奇數),則需要減去a[i]
      •   奇數選: f[i][1] = f[i-1][0]+a[i] //i-1次為0(偶數),則可以加上a[i]
    • 最後只需要取選/不選的最大值存入即可(如圖
    • 技術分享

關於代碼

技術分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 #include <iostream>
 6 
 7 using namespace std;
 8 
 9 int n,a[150001],f[150001][2],num;
10  
11 int main()
12 {
13     ios::sync_with_stdio(0); 
14     cin >> n;
15     for (int i=1;i<=n;i++)
16         cin >> a[i];
17         
18     f[1][0]=a[1];//選第一個 
19     f[1][1]=0;//不選第一個 
20     
21     for (int i=2;i<=n;i++)
22     {
23         f[i][0]=max(f[i-1][1]+a[i],f[i-1][0]);
24         f[i][1]=max(f[i-1][0]-a[i],f[i-1][1]);
25     }
26     
27     num=max(f[n][0],f[n][1]);
28     cout << num;
29     return 0;
30 }
牛跳


2017年8月14日套題記錄 | 普及組