2018NOIP 提高组 Day1

写一波NOIP的题,感觉比我们那时候难多了......可刚刚崔力说我们那一届才是出奇的难.....

https://www.luogu.org/contestnew/show/12952

赛题 #A: P5019 铺设道路

说好的T1签到呢...第一题就想了好久。最后发现贪心可做。对于每一个坑,如果小于前一个,填前一个的时候它已经平了;如果大于前一个,加上超出的数值

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

int n,sum=0;
int a[100010];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sum=a[1];
    for(int i=2;i<=n;i++)
        if(a[i]>a[i-1]) sum+=a[i]-a[i-1];
    printf("%d\n",sum);
    return 0;
}

赛题 #B: P5020 货币系统

网上都在说T1原题,可我总觉得T2之间见到过

根据印象+不严谨的推断,得出一个结论:A 集合内不能被其它数组成的数必然存在于 B  集合内

然后问题就转化为如何找出这些数的总数

这里用到了完全背包

还真巧呢这两天正在搞DP。所谓完全背包,是指对于给你一个体积固定的包和很多商品,每个商品有无数多个,求如何放才能使价值最大。跟其他DP不同,对于完全背包来说,每走一步(即加入一个新的商品),会对之前的几乎所有决策产生影响,因为你不知道“最值”的那个商品何时出现。因此,它的每一步就像是在"反悔":倒退一步看看,如果把目前的商品放进去会不会更好?之所以是几乎所有而非全部,是因为对于那些已占用的体积小于该商品体积的情况,只有一种选择,"反悔"无从谈起.

 for(int i=1;i<=n;i++)        
    for(int j=w[i];j<=c;j++) //从w[i]开始,可以“反悔”了。c为背包总容量。       
        dp[j]=max(dp[j]/*原来的*/,dp[j-w[i]]+v[i]/*新的*/);          

可以看出,有一个从j-w[i]到j的过程.在本题中,对于每一个j,j+w[i]都存在(即能表示出来).像不像是筛法求素数?只不过那里面每个起点都是其质数,这里只要存在,就能作为起点.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

int n,t,ans=0;
int a[110],dp[25100];
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(dp,0,sizeof(dp));
        ans=n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        dp[0]=1;//为了确保有起始点
        for(int i=1;i<=n;i++)
        {
            if(dp[a[i]]) {ans--;continue;}
            for(int j=a[i]/*该数存在,作为起点*/;j<=a[n];j++)
                if(dp[j-a[i]]) dp[j]=1;//如果j-a[i]存在,j就存在
        }
        printf("%d\n",ans);
    }
    return 0;
}

赛题 #C: P5021 赛道修建 | 满分: 100分

又觉得似曾相识......

对于部分数据,很容易写.如果是当年,我大概会开开心心去拿部分分.但......现在是ACM啊,只有AC和不AC两种情况,感觉部分分没太大意义了.留个坑,以后补吧

发布了38 篇原创文章 · 获赞 12 · 访问量 3951

猜你喜欢

转载自blog.csdn.net/int_lyy/article/details/84074748
今日推荐