3月20日一周学习总结

3月20日一周学习总结

贪心算法

(个人对贪心算法的理解:以不断求解局部最优解的方式得到最终的总体解)

节目问题

节目问题的代表题目:给定一组节目的开始和结束时间,求最多能看多少节目。
此类问题一般都以结束时间进行排序,因为从局部来看,当前节目结束的越早,剩余的时间就越多,看更多节目的机会就越大,每次都选取最早结束的节目便可以保证所看的节目最多。

bool cmp(jiemu a,jiemu b)
{
    if(a.en<b.en)
    return 1;
    else if(a.en==b.en)
        {if(a.st<=b.st)
        return 1;
    else return 0;}
    else return 0;
}

(先按结束时间升序排序,当节目结束时间相同时,便再按照开始时间排序)

罚分问题

罚分问题的代表题目:给定一组罚分和截止时间,求最少罚分数。
此类问题也是先进行排序,按时间升序排序,后按照罚分降序排序,当时间相同时,若当前罚分高于之前的最低罚分,与其进行对换,这样可以保证将罚分数降至最少。
(排序部分类似节目问题,不展示排序代码,以下是实现罚分统计的代码)

 int z=1,f=0;
 for(int i=1;i<=n;i++)
        {
            if(f<a[i].day)
            {
            b[z]=a[i].fen;
            z++;
            f++;
            continue;}
            else if(f==a[i].day)
                {for(int j=1;j<z;j++)
            {
                if(b[j]<a[i].fen)
                {

                    tem=a[i].fen;
                    a[i].fen=b[j];
                    b[j]=tem;
                }
            }   s+=a[i].fen;}
        }

(f用来判断天数是否重复,数组b则是记录之前的罚分,当出现罚分高的情况,便通过遍历数组b进行查找罚分最小的情况。)代码仍有待改进
类似问题还有超市利润最大化问题等。

区间调度问题

此类问题可以有多重提问方法,如寻找包含最少数的集合,或者重复最多线段,如搬桌子问题。
搬桌子问题:一条走廊搬桌子,走廊每段一次只能搬一张桌子,求最少搬桌子次数。
将每次搬桌子看做一条线段,线段最多重合数就是搬桌子所需的最少数。
关键部分实现代码:

for(int i=1;i<=n;i++)
            {cin>>be>>en;
            if(be%2==1)
                be+=1;
            if(en%2==1)
                en+=1;
                if(be>en)
                    swap(be,en);
            for(int i=(be/2);i<=(en/2);i++)
            a[i]++;}
        for(int i=1;i<=200;i++)
        {if(a[i]>maxn)
            maxn=a[i];}

因为问题情境是走廊
走廊为如图的对称结构
如图,走廊为对称结构,因此奇数偶数相对应,可以只按一边走廊计算,即只计算偶数房间

价值最大化问题

此类问题包含题目繁多,如背包问题或Java been问题,个人认为是最典型的贪心问题,因为能够明显的体现出贪心的思想。
Java been问题:

 for(int i=0;i<n;i++)
        {
            if(m>0)
            {if(m>=a[i].mao)
                {m-=a[i].mao;
                sum+=a[i].been;}
             else  {
                 sum+=m*a[i].bili;
                    m=0;}}
             else break;
        }

按照兑换率进行降序排序。

数学类问题

此类问题一般难以一眼看出贪心思想,需要进行一定的推导。如物体相撞后变为一个物体,同时质量变为2* sqrt(m1*m2),求最后能得到的最小质量。
个人认为这个问题可以借助一次函数和平方根函数图像来进行判断,可以根据图像直观得出,大的数值开平方减少的越多,所以每次都让最大的元素进行开平方操作即可得到最小数。
可以使用优先队列来保证每次都是最大的数进行运算。

priority_queue<Node> q;
for(int i=1;i<n;i++)
	{
	    double a=q.top().val;
	    q.pop();
	    double b=q.top().val;
	    q.pop();
	    node.val=2*sqrt(a*b);
	    q.push(node);
	}
	printf("%.3f\n",q.top().val);
	q.pop();
    }

删数问题

代表题目:给出一个多位数,删去指定个数的数字后得到的数为最小。
从第一位的俗话开始,若数字走向由升序变为降序或者没有下一个数,则删去这个数。

while(len--)
		{
			temp=t;
			for(i=t;i<=m;++i)
			{
				if(num[temp]>num[i])
					temp=i;
			}
	ans[k++]=num[temp];
			m++;
			t=temp+1;
		}
		i=0;
		while(ans[i]=='0'&&i<k)//去除前导零 
			i++;
		if(i==k)
			printf("0\n");
		else
		{
			for(;i<k;++i)
				printf("%c",ans[i]);
			printf("\n");
		}

因为得数不能以0开头,所以需要去除前导0。

本周学习感悟与收获

这周是第一次接触算法,贪心作为一种基础的算法,既可以用来优化程序,又可以作为一种解题的思路,其重点在于找到贪心的方法,其次在于代码的实现,这周也通过vjudge接触了很多相关的题目,题型较为多变,但其统一具备从局部最优解出发进而得到最终解的思维模式,要掌握这类问题还需见识更多的题目,同时对于ac题目的代码还要进行优化和简化,达到最优解的目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值