【洛谷2019 OI春令營】期中考試

T68402 掃雷

題目連接:傳送門html

題目描述

掃雷,是一款單人的計算機遊戲。遊戲目標是找出全部沒有地雷的方格,完成遊戲;要是按了有地雷的方格,遊戲失敗。如今 Bob 正在玩掃雷遊戲,你做爲裁判要判斷他是否遊戲失敗。c++

具體來講,Bob 正在玩的掃雷遊戲有 n×m 個格子,擁有上帝視角的你知道全部的雷埋在哪些方格。Bob 告訴你他會按哪些格子。若是他按的某個格子有地雷,那麼他遊戲失敗,你須要輸出是哪一步致使他遊戲失敗的;若是他按的全部格子都沒有地雷,那麼他遊戲未失敗,你只需輸出「Good Game.」。app


 

輸入輸出格式

 輸入格式:ide

 

第一行兩個整數 n,m,意義如上所述。函數

接下來 n 行,每行 m 個整數,表示格子的狀況。對於一個位置,若是是 0 表示這個位置沒有地雷,若是是 1 表示有地雷。優化

接下來一行一個整數 k,表示 Bob 的操做次數。spa

接下來 kk 行,其中的第 i 行有兩個整數 xi,yi(1xin,1yim),表示 Bob 的第 i 步按的位置。咱們規定左上角的格子爲 (1,1),右下角的格子爲 (n,m)。3d

你能夠經過樣例進一步理解輸入格式。code

 

輸出格式:htm

 

若是遊戲失敗,輸出是哪一步致使遊戲失敗。若是沒有失敗,輸出「Good Game.」

 

 


 

輸入輸出樣例

輸入樣例#1: 
3 4
0000
0000
0000
1
1 1
輸出樣例#1: 
Good Game.
輸入樣例#2: 
3 4
1000
0000
0000
1
1 1
輸出樣例#2: 
1
輸入樣例#3: 
3 4
1000
0000
0000
2
2 2
1 1

輸出樣例#3: 
2

【題解】:

簡單模擬便可,注意的是輸入按照字符串輸入。
【代碼】:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1000;
 4 int n,m,k;
 5 char a[N][N];
 6 int x[N],y[N],F=1;
 7 int main()
 8 {
 9     scanf("%d%d",&n,&m);
10     for(int i=1;i<=n;i++){
11         scanf("%s",a[i]+1);
12     }
13     scanf("%d",&k);
14     for(int i=1;i<=k;i++){
15         scanf("%d%d",&x[i],&y[i]);
16     }
17     for(int i=1;i<=k;i++){
18         if(a[x[i]][y[i]]=='1'){
19             F = 0;
20             printf("%d\n",i);
21             return 0;
22         }
23     }
24     if(F){
25         puts("Good Game.");
26     }
27     return 0;
28 }
掃雷

 


 

T68401 烤串

題目連接:傳送門

題目描述

經歷了艱辛的掃雷以後,Bob 感到體力不支。他來到了一個烤串店,發現烤串店正在大促銷。促銷策略以下:

一、1 根烤串不賣。

二、2 根烤串賣 5 塊錢。

三、根烤串賣 10 塊錢。

四、12 根烤串賣 17 塊錢。

如今 Bob 有 nn 塊錢,他想知道他最多能夠買多少串烤串。


 

輸入輸出格式

輸入格式:

第一行一個整數 T,表示數據組數。

接下來 T 行,每行一個整數 n,意義如上所述。

 

輸出格式:

輸出 T 行,第 i 行表示第 i 組數據的答案。

 


輸入輸出樣例

輸入樣例#1:
1
34
輸出樣例#1:
24
輸入樣例#2:
2
34
15
輸出樣例#2: 
24
9
 

說明

對於50% 的數據,知足1n100。

對於100% 的數據,知足 1n10^9,1T200。


【題解】:
經典的題目,就是大範圍貪心,小範圍暴力枚舉,或者用徹底揹包處理。
同時注意邊界,以前由於邊界問題錯了好幾次主要是,邊界必定要是全部價錢的公倍數,否則會出錯。
【代碼】:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 4e6+100;
 4 typedef long long ll;
 5 int Val[] = { 12 , 7 , 2 , 0 };
 6 int Cost[] = { 17 , 10 , 5, 1 };
 7 ll dp[N];
 8 void Init(){
 9     memset(dp,-0x7f,sizeof dp );
10     dp[1] = dp[0] = 0 ;
11     for(int i=0;i<4;i++){
12         for(int j=Cost[i];j<=N-1;j++){
13             dp[j] = max( dp[j] , dp[j-Cost[i]] + Val[i] );
14         }
15     }
16 }
17 ll solve( ll n ){
18     if( n < N ) {
19         return dp[n];
20     }
21     ll cnt = ( (n-420+16)/17  ) ;
22 
23     return dp[n - cnt*17 ] + cnt * 12 ;
24 }
25 int main()
26 {
27     Init();
28     ll n;
29     int T;
30     scanf("%d",&T);
31     while(T--){
32         scanf("%lld",&n);
33         ll ans = solve(n);
34         printf("%lld\n",ans);
35     }
36     return 0;
37 }
烤串

 


T68263 排序

題目連接:傳送門

題目描述

Bob 吃完烤串以後又充滿了精力,如今 Alice 給了他一個難題:

有一個長度爲 n 的序列 a1,a2,,an,保證 aiai1(2in)。可是 Alice 修改了其中某 kk 個位置的值,獲得新序列 b1,b2,,bn。Bob 拿到序列 b 以後,但願能夠改不超過 k 個位置的值,使得 b 序列也知足bibi1(2in)。

這個問題對他來講太難了,他想尋求你的幫助。你須要告訴他如何修改使得知足要求。


 

輸入輸出格式

輸入格式:

 

第一行兩個整數n,k,意義如上所述。

接下來一行 n 個整數,第 ii 個整數表示 bi

 

輸出格式:

 

第一行一個整數 t,表示你要修改的次數。須要知足 tk。

接下來 t 行,第 i 行兩個整數 pi,vi,表示將 bpi 修改成 vi。須要知足 1pin,0vi10^9。

若是有多組解符合要求,輸出任意一組便可。你沒必要最小化 t,只要知足 tk 便可。

 


 

輸入輸出樣例

輸入樣例#1: 
5 1
1 2 7 4 5
輸出樣例#1: 
1
3 3
輸入樣例#2: 
5 2
1 2 3 4 5
輸出樣例#2: 
0
 

說明

對於 50% 的數據,知足 1n100。

對於 100% 的數據,知足 1n5000,0kn,0bi10^9。


【題解】:
這個題目也比較經典,涉及的知識點是:最長上升子序列,以及dp記錄路徑問題。
真的很是精妙的題目,之前作過相似的,可是沒有記錄路徑
一、首先求出LIS的長度爲多少。
二、而後求出LIS哪個爲終點,在過程當中注意要記錄路徑。
三、以終點往前跑,把對應的位置改成前一個子序列中元素的值便可。
例如:
序列爲:1 、 2 、 7 、 4 、5
一、找出LIS,最長爲4.
二、以5爲終點時達到最大值。
三、而後進行標記。
12 、 7 、 45

四、最後把對應的位置改爲前一個位置的值。

1 、 2 、 2 、 4 、5
代碼以下:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 int a[N],vis[N],dp[N],from[N];
 5 int n,k;
 6 int main()
 7 {
 8     scanf("%d%d",&n,&k);
 9     for(int i=1;i<=n;i++){
10         scanf("%d",&a[i]);
11     }
12     int First , cnt ,tot;
13     for(int i=1;i<=n;i++){
14         dp[i] = 1 ;
15         from[i] = 0 ;
16         for(int j=1;j<i;j++)if( a[j] <= a[i] ){
17             if( dp[j] + 1 > dp[i] ){
18                 dp[i] = dp[j] + 1 ;
19                 from[i] = j ;
20             }
21         }
22     }
23     int Max_dp = 0 , Max_dp_pos = -1 ;
24     for(int i=1;i<=n;i++){
25         if( dp[i] > Max_dp){
26             Max_dp = dp[i];
27             Max_dp_pos = i;
28         }
29     }
30     //printf("%d %d\n",Max_dp,Max_dp_pos);
31     for(int i = Max_dp_pos; i ; i = from[i] ){
32         //printf("%d %d\n",i,from[i]);
33         vis[i] = 1 ;
34     }
35     printf("%d\n",n-Max_dp);
36     int pre = 0;
37     for(int i=1;i<=n;i++){
38         if( vis[i] == 0 ){
39             printf("%d %d\n",i,pre);
40         }else{
41             pre = a[i] ;
42         }
43     }
44     return 0;
45 }
排序
 
  

 


 

T79670 麻將

題目連接:傳送門

題目描述

高呼三聲 csfnb 後,Alice 和 Bob 開始打牌。

和通常的牌不一樣,他們打的牌上面有兩個點數,分別設爲 a,b。若是 Alice 得到這張牌,她會得到 a 分數;若是 Bob 得到這張牌,他會得到 b 分數。

遊戲開始後,Alice 和 Bob 輪流從牌堆裏拿牌,Alice 先手,直到牌堆的牌被拿完時遊戲結束。Alice 的策略很簡單,她每次選牌堆裏 a 最大的那張牌據爲己有,若是同時有多張牌有一樣的 a,那麼她會取 b 最大的那一張。如今 Bob 想知道他如何選能夠得到最大的分數。

輸入輸出格式

輸入格式:

 

第一行一個整數 n,意義如上所述。

接下來 n 行,第 i 行兩個整數 ai,bi,表示第 i 張牌的點數。

 

輸出格式:

一行一個整數,表示 Bob 按最優策略取的話,能夠得到的最大分數。

 

輸入輸出樣例

輸入樣例#1: 
1
1 23333
輸出樣例#1: 
0
輸入樣例#2: 
2
1 23333
2 1
輸出樣例#2: 
23333

【題解】:這個題目很是精妙,我以爲真的不錯。
首先咱們已經能夠預知的Alice怎麼選擇,咱們只須要在Alice選擇前 ,對於Bob進行預測最優值便可。
這個題目涉及的知識點爲:貪心,排序,堆優化。

首先咱們已經預測到Alice怎麼選擇,咱們直接能夠用Alice的想法進行排序。
這裏用到庫函數Sort()進行排序便可。

而後第二步就是分析Bob的想法,
一、Alice先手,Bob選擇只有比Alice少,不會比Alice多選牌。
二、而後對於Bob來講,對於排序後,偶數張牌是他必選的,奇數時是貪心決策的。
這個就是把大問題變成小問題處理,選第i張牌時,確保第i-1張牌爲最優日後延伸。

舉例子:
排序後的結果
A:  10  9  8  8
B:  5   3  7  2  
首先第一張牌確定是給了Alice
選擇第2張牌時,Bob確定只能選第二張牌,獲得的價值爲3.
選擇第3張牌時,Bob看到第3張牌了。
當前他是能夠優先選擇第3張牌,同時把第2張牌放回去(由於前3張牌只能選1張,Alice先手),獲得的價值爲 7
選擇第4張牌時,只能選擇第4張牌,由於Alice 先手,已經拿去第1,2張牌了。
因此最優策略下,Bob的答案就是9.

在選擇時爲了能找出最小值,而後從新放入的動做,用了Priority_queue優先隊列(堆)來優化。

附上代碼:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+100;
 4 typedef long long ll;
 5 typedef pair<ll,ll> PII;
 6 priority_queue < ll , vector<ll>,greater<ll> > Q;
 7 PII C[N];
 8 int main()
 9 {
10     int n;
11     scanf("%d",&n);
12     for(int i=1;i<=n;i++){
13         scanf("%lld%lld",&C[i].first,&C[i].second);
14     }
15     
16     sort( C+1 , C+1+n , greater<PII>() );
17     
18     long long ans = 0 ,t;
19     if( n>=2 )
20         Q.push(C[2].second),ans=C[2].second;
21     for(int i=3;i<=n;i++){
22         if( i&1 ){
23             t = Q.top();
24             if( !Q.empty() && t < C[i].second ){
25                 ans = ans - Q.top() + C[i].second;
26                 Q.pop();
27                 Q.push(C[i].second);
28             }
29         }else{
30             ans += C[i].second;
31             Q.push(C[i].second);
32         }
33     }
34     return 0*printf("%lld\n",ans);
35 }
麻將
相關文章
相關標籤/搜索