写一波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两种情况,感觉部分分没太大意义了.留个坑,以后补吧