zoukankan      html  css  js  c++  java
  • NOIP2018 Day1

    零年OI一场空,三道原题见祖宗。

    t1道路铺设/积木大赛

    题目描述

    t1 道路铺设/积木大赛题目描述

    思路

    NOIP的时候用的快乐暴力递归,理论上70分,洛谷上80分。
    (其实考试的时候真的要想出来了正解,但是没有怎么实践,太气了!!

    考试70分代码

    /*暴力模拟 70分。 */
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=100005;
    const int inf=10005;
    int d[maxn];
    long long cnt=0;
    int n;
    void build(int l,int r){//暴力 
        if(l>r) return;
        int s=1,v=inf;
        for(int i=l;i<=r;i++) v=min(v,d[i]);
        cnt+=v;
    //	printf("[%d,%d]:%d
    ",l,r,v);
        for(int i=l;i<=r;i++){
            d[i]-=v;
            if(d[i]==0){
                build(s,i-1);
                s=i+1;
            }
        }
        build(s,r);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&d[i]);
        build(1,n);
        printf("%lld",cnt);
        return 0;
    }
    
    

    正解
    考虑下一块的高度和当前积木的高度:
    如果大于:显然需要多搭(现在高度-当前高度)下。
    如果小于:在搭当前这一块积木的时候就能顺便搭这一块,所以不做处理。

    代码

    #include <cstdio>
    #include <iostream>
    using namespace std;
    int main(){
    	int n;scanf("%d",&n);
    	int ans;scanf("%d",&ans);//至少需要搭第一个的高度。
    	int now=ans;//记录当前积木的高度
    	for(int i=2;i<=n;i++){
    		int h;scanf("%d",&h);
    		if(h>now) ans+=(h-now);//如果后面的大于当前的高度 显然要多搭几下
    							//如果小于,那么在搭这一块的时候就能顺便把下一块给搭了
    		now=h; 
    	} 
    	printf("%d",ans);
    	return 0;
    }
    
    

    t2货币系统

    题目描述

    t2货币系统题目描述

    思路

    考试的时候用的超级大筛子,得了90分。

    考试80分代码

    #include <cstdio>
    #include <iostream>
    #include <cstring> 
    #include <algorithm>
    using namespace std;
    const int maxa=1005,maxn=105;
    bool choose[maxa];//能被表示出来 
    int a[maxn];
    int main(){
        int t;scanf("%d",&t);
        while(t--){
            int cnt=0;
            memset(choose,0,sizeof(choose));
            choose[0]=1;
            int n;scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            sort(a+1,a+1+n);
            int end=a[n];
            for(int i=1;i<=n;i++){
                int v=a[i];
                if(!choose[v]){
                    choose[v]=1;
                    cnt++;
                    for(int j=1;j*v<=end;j++){//枚举当前张数
                        int now=j*v;
                        for(int k=1;k<=end;k++){
                            if(now+k>end) break;
                            if(choose[k]) choose[k+now]=1;
                        } 
                    }
                }
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }
    

    正解
    考试的思路与正解真的非常像了,只是有两个问题:
    1、数组太小了,应该为25000(考试的时候看错ai的数据范围不然就有95了,尴尬。)
    2、不用枚举张数,直接一张的时候就行了。
    去掉枚举张数的循环就行了。

    #include <cstdio>
    #include <iostream>
    #include <cstring> 
    #include <algorithm>
    using namespace std;
    const int maxa=25005,maxn=105;
    bool choose[maxa];//能被表示出来 
    int a[maxn];
    int main(){
        int t;scanf("%d",&t);
        while(t--){
            int cnt=0;
            memset(choose,0,sizeof(choose));
            choose[0]=1;
            int n;scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            sort(a+1,a+1+n);
            int end=a[n];
            for(int i=1;i<=n;i++){//当前的钱是否能够表示出来 
            	if(!choose[a[i]]){
            		cnt++;
            		for(int j=0;j+a[i]<=end;j++) if(choose[j]) choose[j+a[i]]=1;
            	}
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }
    
  • 相关阅读:
    结对编程实验(1李晓冬13、张金伟118)
    软件工程网络15个人阅读2(201521123118张金伟)
    软件工程网络15个人作业阅读1(201521123118 张金伟)
    《Java课程设计》
    201521123118《java与程序设计》第14周学习总结
    201521123118《程序与设计》第13周学习总结
    201521123118《程序与设计》第12周学习总结
    网络15软工个人作业5——软件工程总结
    个人作业4——alpha阶段个人总结
    软工网络15个人作业3——案例分析
  • 原文地址:https://www.cnblogs.com/saitoasuka/p/9940083.html
Copyright © 2011-2022 走看看