acm训练第一周
10小时训练量对我新加入acm人员来说的确是一个挑战,我也会调整好自己态度,努力跟上大佬的脚步!!!。
- 7.7号训练内容
1.今天做了一到贪心题目:洛谷P5019 铺设道路 难度:普及- 题目不难第一眼我想的是分治的做法:找到begin到end的最小值的位置pos,并将最小值设为a[pos],其他的数都减去min,再将天数加上min。然后分治以(begin,pos-1)和(pos+1,end)两部分继续上列步骤。
源代码:
#include<iostream>
using namespace std;
int a[100000+5],day=0;
void road(int begin,int end) //分治
{
if(begin>end) return; //退出条件
int pos,min=10005;
for(int i=begin;i<=end;i++)
if(min>a[i]) {min=a[i];pos=i;} //找出最小值和位置pos
day+=min;
for(int i=begin;i<=end;i++) //天数加上min'
a[i]-=min;
road(begin,pos-1);
road(pos+1,end); //继续上列步骤,重复直到退出
}
int main()
{
int n; cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
road(1,n);
cout<<day<<endl;
return 0;
}
ps:分治也是之前通过看大佬题目才认识到的,比如快速排序 看完之后恍然大悟,还有求最大数列和也是用分治方法。用起来的确非常爽。
7.8号今天做了一道贪心题目洛谷P1803,和*今年暑假不ac几乎一摸一样,之前没有好好去做,现在可以写一下。
所谓贪心就是贪取最大利益,这题看起来挺简*单的,实际上也是挺简单的。这题不需要动态规划,因为将每个活动结束的时间从小到大排个序,然后再线性的比较每个活动开始时间与前面已经选中活动结束的时间经行比较:若开始时间要>=结束时间则选中然后更新时间,否则跳过
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct{
int a,b;
}timet;
timet t[1000000+5];
int cmp(const timet&Time,const timet&TIME)
{
if(Time.b<TIME.b) //根据b值从小到大排序
return 1;
else
return 0; //这里出现了一个大错误,就是因为没有return 0导致排序失效了
}
int main()
{
int n;cin>>n;
for(int i=0;i<n;i++)
cin>>t[i].a>>t[i].b;
sort(t,t+n,cmp);
int num=1;
int b=t[0].b;
for(int i=1;i<n;i++)
if(t[i].a>=b)
{
b=t[i].b;
num++;
}
cout<<num;
return 0;
}
ps:代码里面出现了一个错位,在用cmp函数的时候只想到了return 1而下面的情况没有return 0的时候发现排序成了乱序!!!!(一定要记住)
7.9号 之前买的算法书看到我头皮发麻,不明所以。重新了买了本算法竞赛进阶指导,还没有到。。。。。。。
不过今天又是贪心的一天呢!做了道洛谷P3817 小A的糖果。思想是对的,算法也是对的然后哦豁,就很离谱的wa了。一直不知道是哪错了,最后!!!原来是一个非常非常小的错误
(算法思想下面已经出来了:如果当前这个数大于x则sum加上多余的数,a[i]=x;若a[i]+a[i+1]>x,sum再加上多余的数,a[i+1]=x-a[i]😉
#include<iostream>
using namespace std;
int a[100000+5];
int main()
{
int n,x,i;
cin>>n>>x;
for(i=0;i<n;i++)
cin>>a[i];
long long sum=0;
for(i=0;i<n-1;i++)
{
if(a[i]>x) {sum+=a[i]-x;a[i]=x;} //如果a[i]大于x则sum加上多余的数,将a[i]=x
if(a[i]+a[i+1]>x) //为谋取最优解应该在a[i+1]上面进行运算
{
sum+=a[i]+a[i+1]-x;
a[i+1]=x-a[i];
}
}
cout<<sum;
return 0;
}
*没错就是再第一个注释那儿我写成了 a[i]-=x; 很愚蠢 ! 一定要吸取教训