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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章