NOIP 提高组 初赛 四、阅读程序写结果 习题集(七)NOIP2010-NOIP2011

NOIP 提高组 初赛 四、阅读程序写结果 习题集(七)NOIP2010-NOIP2011

1.第十六届(NOIP2010)

问题

1.

//2010.4.1
#include <stdio.h>
#define size 10
int main(){
    int i,j,cnt,n,m;
    int data[size];
    scanf("%d%d\n",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&data[i]);
    for(i=1;i<=n;i++){
        cnt=0;
        for(j=1;j<=n;j++)
            if(data[i]<data[j]||(data[j]==data[i]&&j<i))
                cnt++;
        if(cnt==m)
            printf("%d\n",data[i]);
    }
    return 0;
}
//输入:
//5 2
//96 -8 0 16 87
 

2.

//2010.4.2
#include <stdio.h>
#define size 100
int main(){
    int na,nb,i,j,k;
    int a[size],b[size];
    scanf("%d\n",&na);
    for(i=1;i<=na;i++)
        scanf("%d",&a[i]);
    scanf("%d\n",&nb);
    for(i=1;i<=nb;i++)
        scanf("%d",&b[i]);
    i=1;
    j=1;
    while(i<=na&&j<=nb){
        if(a[i]<=b[j]){
            printf("%d ",a[i]);
            i++;
        }else{
            printf("%d ",b[j]);
            j++;
        }
    }
    if(i<=na)
        for(k=i;k<=na;k++)
            printf("%d ",a[k]);
    if(j<=nb)
        for(k=j;k<=nb;k++)
            printf("%d ",b[k]);
    return 0;
}
//输入:
//5
//1 3 5 7 9
//4
//2 6 10 14

3.

//2010.4.3
#include <stdio.h>
#define num 5
int r(int n){
    int i;
    if(n<=num)
        return n;
    for(i=1;i<=num;i++)
        if(r(n-i)<0)
            return i;
    return -1;
}
int main(){
    int n;
    scanf("%d",&n);
    printf("%d\n",r(n));
    return 0;
}
//输入:16
 

4.

//2010.4.4
#include <stdio.h>
#include <string.h>
#define size 100
int n,m;
int r[size];
int map[size][size];
int find;
int successful(){
    int i;
    for(i=1;i<=n;i++)
        if(map[r[i]][r[i%n+1]]==0)
            return 0;
    return 1;
}
void swap(int *a,int *b){//此处网络流传的pascal写法应该是有问题的
    int t;
    t=*a;
    *a=*b;
    *b=t;
}
void perm(int left,int right){
    int i;
    if(find==1)
        return;
    if(left>right){
        if(successful()==1){
            for(i=1;i<=n;i++)
                printf("%d ",r[i]);
            find=1;
        }
        return;
    }
    for(i=left;i<=right;i++){
        swap(r+left,r+i);
        perm(left+1,right);
        swap(r+left,r+i);
    }
}
int main(){
    int x,y,i;
    scanf("%d%d",&n,&m);
    memset(map,0,sizeof(map));
    for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        map[x][y]=1;
        map[y][x]=1;
    }
    for(i=1;i<=n;i++)
        r[i]=i;
    find=0;
    perm(1,n);
    if(find==0)
        printf("No solution\n");
    return 0;
}
//输入:
/*
9 12
1 2
2 3
3 4
4 5
5 6
6 1
1 7
2 7
3 8
4 8
5 9
6 9
*/
 

问题解答:

1.读程序,并试着执行,很快能发现,是在5个输入数据中找到第三大的数,

很快得出答案:16

1简单

2.顺着程序执行,很快就能得到答案,思考过程如图所示:


答案:1 2 3 5 6 7 9 10 14

2简单

3.该题是自下而上练习递归的好题。

从r(16)开始执行此题很难,自下而上开始执行,此题比较简单。

出答案分分钟的事。思考过程如图所示:



答案:4

3简单

4.此题模拟了

perm(1,1)打印No solution

perm(1,2)打印1 2

perm(1,3)打印No solution

没发现什么规律,暂放弃。

答案:1 6 9 5 4 8 3 2 7

来自http://blog.sina.com.cn/s/blog_8c35725a0100xddr.html

④     求哈密尔顿回路

这题的关键是看懂successful函数的含义。搜索的过程并不难看懂,如果实在看不懂手动模拟一下也能看出来是一个对于r[n]方案的枚举,successful是判断r[n]里储存的方案是否是一个合法的哈密尔顿回路。当然这题一个非常非常易错的地方就是搜索的顺序决定了输出的方案必定是所有可行方案的字典序最小的一个,尽管输入数据只有两组方案,但是由于输入数据给定的顺序问题,也有许多同学忽略了这个问题,造成不必要的失分。


2016-12-27

1.第十七届(NOIP2011)

问题

1.

//2011.4.1
#include <stdio.h>
#include <string.h>
#define size 100
int main(){
    int n,i,sum,x;
    int a[size];
    scanf("%d",&n);
    memset(a,0,sizeof(a));
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        a[x]++;
    }
    i=0;
    sum=0;
    while(sum<(n/2+1)){
        i++;
        sum+=a[i];
    }
    printf("%d\n",i);
    return 0;
}
//输入:11
//4 5 6 6 4 3 3 2 3 2 1
 

2.

//2011.4.2
#include <stdio.h>
int n;
void f2(int x,int y);
void f1(int x,int y){
    if(x<n)
        f2(y,x+y);
}
void f2(int x,int y){
    printf("%d ",x);
    f1(y,x+y);
}
int main(){
    scanf("%d",&n);
    f1(0,1);
    return 0;
}
//输入:30
 

3.

//2011.4.3
#include <stdio.h>
#define v 100
int visited[v];
int e[v][v];
int n,m,ans;
void dfs(int x,int len){
    int i;
    visited[x]=1;
    if(len>ans)
        ans=len;
    for(i=1;i<=n;i++)
        if(visited[i]==0&&e[x][i]!=-1)
            dfs(i,len+e[x][i]);
    visited[x]=0;
}
int main(){
    int i,j,a,b,c;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            e[i][j]=-1;
    for(i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        e[a][b]=c;
        e[b][a]=c;
    }
    for(i=1;i<=n;i++)
        visited[i]=0;
    ans=0;
    for(i=1;i<=n;i++)
        dfs(i,0);
    printf("%d\n",ans);
    return 0;
}
//输入:
/*
4 6
1 2 10
2 3 20
3 4 30
4 1 40
1 3 50
2 4 60
*/

4.

//2011.4.4
#include <stdio.h>
#include <string.h>
#define size 10000
#define length 10
int n,m;
int a[size][length];
int h(int u,int v){
    int ans,i;
    ans=0;
    for(i=1;i<=n;i++)
        if(a[u][i]!=a[v][i])
            ans++;
    return ans;
}
int main(){
    int sum,i,j;
    scanf("%d",&n);
    memset(a,0,sizeof(a));
    m=1;
    while(1){
        i=1;
        while(i<=n&&a[m][i]==1)
            i++;
        if(i>n)
            break;
        m++;
        a[m][i]=1;
        for(j=i+1;j<=n;j++)
            a[m][j]=a[m-1][j];
    }
    sum=0;
    for(i=1;i<=m;i++)
        for(j=1;j<=m;j++)
            sum+=h(i,j);
    printf("%d\n",sum);
    return 0;
}
//输入:7
 

问题解答:

1.该题比较简单,顺着程序执行,思考过程如图所示:


答案:3

1简单

2.该题比较简单,该题也是练递归的好题,顺着程序执行,思考过程如图所示:


答案:1 2 5 13 34

2简单

3.思考过程如图所示,试着跟踪程序一个分支到底,试图弄明白程序意图。


该程序遍历所有的点,不能重复,找出最大长度。即一笔画,找出最大长度。思考过程如图所示:

答案:60+40+50=150

3中等

4.思考过程如图所示:


费了好大劲,才弄明白,程序是模拟二进制加法,每次加1。

最终m=128.

接下来,再也无力处理sum部分,如果是考试,此时只能放弃了。

参考http://wenku.baidu.com/link?url=j_VjatBanHeEfnRpqHD6b_eJo0vK8BR5ddr3CKpQ7YfEUpqhdqEO3Ecl41GPDf4X3qhSBkKbM9AvWfAGAAmhc8cqAleYxjr3C5fEP3ejD67

不过没看懂,不过坚定了能做出的信心,后细细思考,得出答案,将过程表述如下。

每列有128个数,其中64个0,64个1。

故每列中任取一个数,与其它127个数不同的计数有64个。

一共有7列,计数64*7

共128行,计数64*7*128=57344

答案:57344

4难

2016-12-28

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值