zoukankan      html  css  js  c++  java
  • 6.19noip模拟赛总结

    昨天进行了noip的模拟赛,我这个蒟蒻又是垫底....

    T1

     第一感觉就是贪心,从高到低排序,然后每次都将恰好满足当前条件的人数分成一组,然后移动到下一个未分组的单位上,贴代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1110000;
    int d[N],ans;
    bool cmp(int a,int b)
    {
    	return a>b;
    }
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&d[i]);
    	sort(d+1,d+1+n,cmp);
    	int pos=1;
    	while(pos!=n+1)
    	{
    		ans++;
    		pos+=d[pos];
    	}
    	printf("%d
    ",ans);
    }
    

    只能拿80分,存在反例 4 4 4 4 3 1 1 1 ,贪心的话得到3,最优解是4,所以这样贪心是有问题的,老师说贪心可以过,但我不会写....

    正解是dp,从小到大排序,对于每个i,都可以与包括他的前面的d[i]个人分为一组,所以定义dp[i]为满足前i个人条件所能构成队伍数量的最大值,得到转移式:dp[i]=max{dp[j],0<j<=i-d[i]}+1

    但这样的话有两层循环,时间复杂度是n的平方,而数据范围为10^6,会超时,所以要优化一下,大概就是保证dp[i] 为dp[1]到dp[i] 的最大值,然后就可以省去枚举j,贴代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1110000;
    int d[N],dp[N];
    int main()
    {
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&d[i]);
    	sort(d+1,d+1+n);
    	for(int i=1;i<=n;i++)
    	{
    		if(i>=d[i]) dp[i]=dp[i-d[i]]+1;
    		dp[i]=max(dp[i],dp[i-1]);
    	}
    	printf("%d
    ",dp[n]);
    	return 0;
    } 
    

    T2

    我写的dfs...然后莫名RE...

    有同学写的bfs,也非常易懂,不会出现爆栈的危险,但最后几个点超时

    #include <bits/stdc++.h>
    using namespace std;
    int n;
    struct node{
    	int l,r,t;
    };
    queue <node>q;
    int main(){
    	scanf("%d",&n);
    	node temp,x1,x2;
    	temp.l=1;temp.r=1;temp.t=0;
    	q.push(temp);
    	while(!q.empty()){
    		temp=q.front();
    		q.pop();
    		if((temp.l+temp.r)==n) {
    			printf("%d",temp.t+1);
    			return 0;
    		}
    		if((temp.l+temp.r)<n){
    			x1.l=temp.l+temp.r;x1.r=temp.r;x1.t=temp.t+1;
    			q.push(x1);
    			x2.l=temp.l;x2.r=temp.l+temp.r;x2.t=temp.t+1;	
    			q.push(x2);	
    		}
    	}
    	return 0;
    }
    

    可以发现,对于一个数对(a,b),当a>b时,可由(a-b,b)得到;当a<b时,可由(a,b-a)得到;当a=b时,不可能由(1,1)变换得到;

    所以我们可以倒着推,设T(a,b)为从(1,1)变换成(a,b)所需要的次数,在a/b时,有T(a,b)=T(b,a%b)+a/b,所以可以剪枝

    答案为min{T(n,i),0<i<=n}

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int check(int a,int b)
    {
    	if(b==1)return a-1;
    	if(!b) return 1e8;
    	return a/b+check(b,a%b);
    }
    int main()
    {
    	int n,ans=1e8;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		ans=min(check(n,i),ans);
    	printf("%d
    ",ans);
    	return 0; 
    } 
    

    T3

    待编辑

  • 相关阅读:
    Windows SDK编程(Delphi版) 之 应用基础,楔子
    一个小问题引发的论证思考
    Delphi 组件开发教程指南(7)继续模拟动画显示控件
    用PyInstaller将python转成可执行文件exe笔记
    使用 .Net Memory Profiler 诊断 .NET 应用内存泄漏(方法与实践)
    Microsof Office SharePoint 2007 工作流开发环境搭建
    How to monitor Web server performance by using counter logs in System Monitor in IIS
    LINQ之Order By
    window 性能监视器
    内存泄露检测工具
  • 原文地址:https://www.cnblogs.com/greengenius/p/9204085.html
Copyright © 2011-2022 走看看