1. 程式人生 > >賽後總結2018-08-13

賽後總結2018-08-13

第一題:

【題目描述】
農夫約翰被通知,他的一隻奶牛逃逸了!所以他決定,馬上出發,儘快把那隻奶牛抓回來.
他們都站在數軸上.約翰在N(ON100000)處,奶牛在K(OK100000)處.約翰有兩種辦法移動,步行和瞬移:步行每秒種可以讓約翰從x處走到x+l或x-l處;而瞬移則可讓他在1秒內從x處消失,在2x處出現.然而那隻逃逸的奶牛,悲劇地沒有發現自己的處境多麼糟糕,正站在那兒一動不動.
   那麼,約翰需要多少時間抓住那隻牛呢?
【輸入格式】
僅有兩個整數NK
【輸出格式】
最短時間
【樣例輸入】
5 17
【樣例輸出】
4

這一題就很水了,直接暴力搜尋即可,這裡就直接給出程式碼了:
AC程式碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int a[maxn],b[maxn],c[maxn],tot;
int DFS(int szsh){
    if(c[szsh]!=0) 
       DFS(c[szsh]);
    tot++;
}
int main(){
    int n,k,x;
    cin>>n>>k;
    if(n==k){
       cout<<0<<endl;
       return 0;
    }
    a[1
]=n; b[n]=1; int head=0,tail=1; while(head!=tail){ head++; for(int i=1;i<=3;i++){ if(i==1) x=a[head]+1; if(i==2) x=a[head]-1; if(i==3) x=a[head]*2; if(x>=0&&b[x]==0&&x<=100000
){ tail++; a[tail]=x; c[tail]=head; if(x==k){ DFS(tail); cout<<tot-1<<endl; head=tail; break; } b[x]=1; } } } return 0; }

第二題:

【題目描述】
FJ打算好好修一下農場中某條凹凸不平的土路。按奶牛們的要求,修好後的路面高度應當單調上升或單調下降,也就是說,高度上升與高度下降的路段不能同時出現在修好的路中。 整條路被分成了N段,N個整數A_1, ... , A_N (1 <= N <= 2,000)依次描述了每一段路的高度(0 <= A_i <= 1,000,000,000)。FJ希望找到一個恰好含N個元素的不上升或不下降序列B_1, ... , B_N,作為修過的路中每個路段的高度。由於將每一段路墊高或挖低一個單位的花費相同,修路的總支出可以表示為: |A_1 - B_1| + |A_2 - B_2| + ... + |A_N - B_N| 請你計算一下,FJ在這項工程上的最小支出是多少。FJ向你保證,這個支出不會超過2^31-1
【輸入格式】
 第1行: 輸入1個整數:N * 第2..N+1行: 第i+1行為1個整數:A_i
【輸出格式】
第1行: 輸出1個正整數,表示FJ把路修成高度不上升或高度不下降的最小花費
【樣例輸入】
7
1
3
2
4
5
3
9
【樣例輸出】
3
【樣例解釋】
FJ將第一個高度為3的路段的高度減少為2,將第二個高度為3的路段的高度增加到5,總花費為|2-3|+|5-3| = 3,並且各路段的高度為一個不下降序列 1,2,2,4,5,5,9。

這一題顯然就比上一題難了,顯然,這是一個DP加上最長不下降子序列以及最長不上升子序列問題,這樣就得離散化處理,對於前i個數,我們需要關心的有兩個值
1.把它變成單調序列需要的土,越少越好
2.第i個數的大小,越小越好
於是dp[i][j]表示考慮前i個數,第i個數是j時,至少需要的土第i個數是j時最少需要的土,就等於j和a[i]差的絕對值+ 第i-1個數小於等於j時至少需要土的最小值並且得結合滾動陣列,得出狀態轉移方程:dp[i-1][j]=abs(a[i]-b[j])+min(dp[i-1][j]);
程式碼如下:

#include <bits/stdc++.h>
const int maxn=2000+10;
using namespace std;
int dp[maxn*3][maxn*3],a[maxn],b[maxn],t,ans,n;
int min(int a,int b){
    return a<b?a:b;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
        dp[1][i]=abs(a[1]-b[i]);
    for(int i=2;i<=n;i++){
        int k=dp[i-1][1],temp;
        for(int j=1;j<=n;j++){
            k=min(dp[i-1][j],k);
            temp=abs(a[i]-b[j]);
            dp[i][j]=k+temp;
        }
    }
    ans=dp[n][n];
    for(int i=1;i<n;i++)
        ans=min(ans,dp[n][i]);
    cout<<ans;
    return 0;
}

第三題直接騙分輸出n-1竟然蒙對了兩個樣例點!!!rp也是夠可以了。