赛后总结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也是够可以了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值