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

    待编辑

  • 相关阅读:
    跨浏览器 JavaScript判断窗口是否最小化
    .net 5 获取用户真实IP(nginx)
    C# EF 字符串模糊查询完整实例 lambda
    (zt)过程生成
    (zt)IOS开发常用的开源类库和一些示例
    wp7 生命周期及多任务 详解
    Js中concat()与push()的区别
    Ruby中p、print和puts的区别
    jquery Bug:当表单中包含name为nodeType的input时jquery选择器失效的bug 与您分享我的快乐
    Openlaszlo学习(一)Demo "Applying Constraints"的修改 与您分享我的快乐
  • 原文地址:https://www.cnblogs.com/greengenius/p/9204085.html
Copyright © 2011-2022 走看看