「算法競賽入門經(jīng)典」「第三章」

開燈問題(P39)

n盞燈,編號為1-n匠璧,第一個人把所有燈打開,第二個人按下編號為2的倍數(shù)的燈的開關(guān)咸这,第三個人按下編號為3的倍數(shù)的燈的開關(guān)夷恍,以此類推,一共有k個人炊苫,問最后有哪些燈開著裁厅。

// 3開燈問題.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    int n,k;
    int a[1005];
    int first = 0;
    while(scanf("%d%d",&n,&k)){
        memset(a,0,sizeof(a));
        for(int i=1;i<=k;i++){
            for(int j=1;j<=n;j++){
                if(j%i==0)a[j] = !a[j];
            }
        }
        for(i=1;i<=n;i++){
            if(a[i]){
                if(first==0){printf("%d",i);first=1;}
                else printf(" %d",i);
            }
        }
        printf("\n");
    }
    return 0;
}

蛇形填數(shù)(P39)

在n*n的方陣?yán)锾钊?,2,3...,n*n侨艾,要求填成蛇形执虹。例如,n=4時的方陣為:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
先判斷唠梨,再填數(shù)袋励。這個題必須得建立二維數(shù)組才輸出成這樣,所以不要猶豫当叭。

// 3蛇形填數(shù).cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    int n;
    int a[10][10];
    while(scanf("%d",&n)){
        memset(a,0,sizeof(a));
        int tot = 0;
        int x = 0;
        int y = n-1;
        a[x][y] = ++tot;
        while(tot<n*n){
            while(x+1 <= n-1 && a[x+1][y] == 0) a[++x][y] = ++tot;  
            while(y-1 >= 0 && a[x][y-1] == 0) a[x][--y] = ++tot;
            while(x-1 >= 0 && a[x-1][y] == 0) a[--x][y] = ++tot;
            while(y+1 <= n-1 && a[x][y+1] == 0) a[x][++y] = ++tot;  
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                printf("%3d",a[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}
豎式問題(P41)

最開始無從下手茬故,但其實已經(jīng)遇到很多這樣的循環(huán)枚舉的題目了,就從題意開始蚁鳖,枚舉三位數(shù)和兩位數(shù)磺芭。
strchr(a,'b')是在字符串a(chǎn)中查找b字符,如果找不到就返回NULL醉箕,strlen返回字符串真實長度钾腺。

// 3豎式問題.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    char num[11];
    while(scanf("%s",num)){
        int count = 1;
        for(int i=100;i<1000;i++){
            for(int j=10;j<100;j++){
                int ok = 1;
                int abc = i;
                int de = j;
                int temp1 = abc * (de%10);
                int temp2 = abc * (de/10);
                int temp3 = abc * de;
                char buf[50];
                sprintf(buf,"%d%d%d%d%d",abc,de,temp1,temp2,temp3);
                for(int q=0;q<strlen(buf);q++){
                    if(strchr(num,buf[q])==NULL) ok = 0;
                }
                if(ok){
                    printf("<%d>\n",count++);
                    printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n",abc,de,temp1,temp2,temp3);
                }
            }
        }
        printf("\nThe number of solutions = %d\n",--count);
    }
    return 0;
}
例題3-1 TeX中的引號(UVa272)(P45)

這個題主要就是知道了

int c;
c = getchar();
是正確的
char c;
c = getchar();
是錯誤的,因為getchar的返回值是int型讥裤。

EOF表示End Of File放棒,表示輸入流的結(jié)尾,其代表的是-1己英,用char類型來表示負數(shù)是錯誤的间螟,所以是int。
scanf("%s",s)在讀取字符串的時候损肛,遇到空格厢破,Tab,換行都會停止讀取治拿。

例題3-2 WERTYU(UVa10082)(P47)

鍵盤輸入右錯一位摩泪,輸入一個錯位后的字符串,均大寫忍啤,輸出錯位修正后的字符串加勤。

// lt32.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
    char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";
    int c;
    while((c=getchar())!=EOF){
        for(int i=0;i<strlen(s);i++){
            if(s[i] == c){putchar(s[i-1]);break;}
        }
        if(i == strlen(s))putchar(c);
    }
    printf("\n");
    return 0;
}
3-3回文詞(UVa401)

判斷一個字符串是否是回文串,以及鏡像串

// lt33.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>

char mirror[] = "A   3  HIL JM O   2TUVWXY51SE Z  8 ";
char fun(char c){
    if(isalpha(c))return mirror[c-'A'];
    else return mirror[c-'0'+25];
}
int main(int argc, char* argv[])
{
    char input[30];
    char* msg[] = {"is not a palindrome","is a regular palindrome","is a mirrored string","is a mirrored palindrome"};

    char ch[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
    
    while(scanf("%s",input)){
        int p=1,m=1;
        for(int i=0;i<(strlen(input)+1)/2;i++){
            //這塊不能判斷相等然后賦值為1同波,邏輯會出現(xiàn)錯誤
            if(input[i] != input[strlen(input)-1-i]) p=0;
            if(fun(input[i]) != input[strlen(input)-1-i]) m=0;
        }
        /*
        printf("%s -- ",input);
        if(m+p==0)printf("%s.\n",msg[0]);
        if(m+p==1){
            if(m==1) printf("%s.\n",msg[2]);
            else printf("%s.\n",msg[1]);
        }
        if(m+p==2)printf("%s.\n",msg[3]);
        */
        printf("%s -- %s.\n.\n",input,msg[2*m+p]);
    }
    return 0;
}
例題3-4猜數(shù)字游戲的提示(UVa 340)

給定答案序列和用戶猜的序列鳄梅,統(tǒng)計有多少數(shù)字位置正確(A),有多少數(shù)字在兩個序列都出現(xiàn)但位置不對(B)
又是一個枚舉循環(huán)未檩,對于每個數(shù)字統(tǒng)計兩個序列中數(shù)字出現(xiàn)的次數(shù)戴尸,兩個次數(shù)取最小值,注意時每個數(shù)字都要取最小值然后累加到B上冤狡,最后B減A孙蒙。

// lt34.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#define min(a,b) a>b?b:a
int main(int argc, char* argv[])
{
    int count;
    int num = 1;
    while(scanf("%d",&count)&&count){
        printf("Game %d:\n",num++);
        int a[1005],s[1005];
        for(int i=0;i<count;i++){
            scanf("%d",s+i);
        }
        while(1){
            int sum=0;
            int A=0,B=0;
            for(int i=0;i<count;i++){
                scanf("%d",a+i);
                sum += a[i];
            }
            if(sum == 0)break;
            for(i=0;i<count;i++){
                if(a[i] == s[i]) A++;
            }
            
            for(i=1;i<=9;i++){
                int b1=0,b2=0;
                for(int j=0;j<count;j++){
                    if(a[j] == i)b1++;
                    if(s[j] == i)b2++;
                }
                B += min(b1,b2);
            }
            printf("(%d,%d)\n",A,B-A);
        }
    }
    return 0;
}

例題3-5 生成元(UVa1583)(P52)
如果x加上x的各個數(shù)字之和得到y(tǒng),就說x是y的生成元悲雳。給出n(1<=n<=100000)挎峦,求最小生成元,無解輸出零合瓢。
第一次做查表的題目坦胶。遇到一個數(shù)就枚舉的話,效率并不高晴楔,因為很明顯每個數(shù)只會對應(yīng)一個固定的結(jié)果顿苇,所以完全可以把這些結(jié)果都提前計算好,并存儲起來税弃,輸出結(jié)果就直接查表纪岁。

// lt35.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{   
    int ans[100005];
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=100000;i++){
        int x=i,y=i;
        while(x>0){
            y += x%10;
            x = x/10;
        }
        if(ans[y] == 0 || i < ans[y]) ans[y] = i;
    }
    int count;
    int n;
    scanf("%d",&count);
    while(count--){
        scanf("%d",&n);
        printf("%d\n",ans[n]);
    }
    return 0;
}
例題3-6 環(huán)狀序列(UVa1584)

最近在網(wǎng)上提交這道題,至少還是參加過比賽的则果,完全忘記了提交注意事項幔翰。

1.因為是用VC寫的,#include "stdafx.h"會有這么一個頭短条,在提交時不要加上导匣。
2.我覺得VC違背了c語言的塊級作用域,如圖使用會報重復(fù)定義的錯茸时。但不應(yīng)該報錯的贡定,應(yīng)該使用其他IDE不會出現(xiàn)這種情況,不得已提出i的定義可都,放在最開始缓待。點這個網(wǎng)友回答蠻好的

一句話夠了,取余來實現(xiàn)循環(huán)渠牲。

// lt36.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

int less(char *s,int p,int q){
    int n = strlen(s);
    for(int i=0;i<n;i++){
        if(s[(p+i)%n] != s[(q+i)%n])
            return s[(p+i)%n] < s[(q+i)%n];
    }
    return 0;
}
int main(int argc, char* argv[])
{

    int count;
    scanf("%d",&count);
    char s[105];
    while(count--){
        int ans = 0;
        int i;
        scanf("%s",s);
        for(int i=0;i<strlen(s);i++){
            if(less(s,i,ans)) ans = i;
        }
        for(int i=0;i<strlen(s);i++){
            putchar(s[(ans+i)%strlen(s)]);
        }
        printf("\n");
    }
    return 0;
}
習(xí)題3-1 得分(UVa1585)

簡單題

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    int T;
    scanf("%d",&T);
    while(T--){
        char s[85];
        scanf("%s",s);
        int tot = 0,sum =0;
        for(int i=0;i<strlen(s);i++){
            if(s[i] == 'O') {tot++;sum+=tot;}
            else tot = 0;
        }
        printf("%d\n",sum);
    }
    return 0;
}
習(xí)題3-2 分子量(UVa1586)
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int fun(int A,char *str,int i){
    if(isdigit(str[i+1])){
        if(isdigit(str[i+2])){
            A += str[i+2] - '0';
            A += (str[i+1] - '0')*10;
        }
        else
            A += str[i+1] - '0';
    }
    else A++;
    return A;
} 
int main(int argc, char* argv[])
{
    float ch[] = {12.01,1.008,16.00,14.01};
    int T;
    scanf("%d",&T);
    while(T--){
        char str[85];
        int C=0,H=0,O=0,N=0;
        scanf("%s",str);
        for(int i=0;i<strlen(str);i++){
            if(str[i] == 'C'){
                C = fun(C,str,i);
            }
            else if(str[i] == 'H'){
                H = fun(H,str,i);
            }
            else if(str[i] == 'O'){
                O = fun(O,str,i);
            }
            else if(str[i] == 'N'){
                N = fun(N,str,i);
            }
        }
        float sum = ch[0]*C+ch[1]*H+ch[2]*O+ch[3]*N;
        printf("%.3f\n",sum);
    }
    return 0;
}

這個使用傳址實現(xiàn)旋炒,比較方便,最開始*A沒有加括號签杈,導(dǎo)致程序出現(xiàn)錯誤瘫镇,所以一定要記得指針在運算時一定要加括號鼎兽。

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void fun(int *A,char *str,int i){
    if(isdigit(str[i+1])){
        if(isdigit(str[i+2])){
            (*A) += str[i+2] - '0';
            (*A) += (str[i+1] - '0')*10;
        }
        else
            (*A) += str[i+1] - '0';
    }
    else (*A)++;
} 
int main(int argc, char* argv[])
{
    float ch[] = {12.01,1.008,16.00,14.01};
    int T;
    scanf("%d",&T);
    while(T--){
        char str[85];
        int C=0,H=0,O=0,N=0;
        scanf("%s",str);
        for(int i=0;i<strlen(str);i++){
            if(str[i] == 'C'){
                fun(&C,str,i);
            }
            else if(str[i] == 'H'){
                fun(&H,str,i);
            }
            else if(str[i] == 'O'){
                fun(&O,str,i);
            }
            else if(str[i] == 'N'){
                fun(&N,str,i);
            }
        }
        float sum = ch[0]*C+ch[1]*H+ch[2]*O+ch[3]*N;
        printf("%.3f\n",sum);
    }
    return 0;
}
習(xí)題3-3 數(shù)數(shù)字UVa1225
#include <stdio.h>
#include <string.h>
char s[100000];
int main(int argc, char* argv[])
{
    int T;
    scanf("%d",&T);
    while(T--){
        int q[10];
        memset(q,0,sizeof(q));
        memset(s,'\0',sizeof(s));
        int num,i;
        scanf("%d",&num);
        for(i=1;i<=num;i++){
            char buf[10];
            sprintf(buf,"%d",i);
            strcat(s,buf);
        }
        for(i=0;i<strlen(s);i++){
            q[s[i]-'0']++;
        }
        for(i=0;i<9;i++){
            printf("%d ",q[i]);
        }
        printf("%d\n",q[9]);
    }
    return 0;
}
習(xí)題3-4 周期串UVa455

像這種類似循環(huán)的題目,跟取余一定有關(guān)系铣除。原題里的空行我一直沒讀懂谚咬,尷尬英語不好。

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    int T;
    scanf("%d",&T);
    while(T--){
        char str[85];
        scanf("%s",str);
        int length = strlen(str);
        for(int i=1;i<=length;i++){
            if(length%i == 0){
                int j;
                for(j=0;j<length;j++){
                    if(str[j] != str[j%i]) break;
                }
                if(j == length){
                    printf("%d\n",i);
                    break;
                }
            }
        }
        if (T) printf("\n");  
    }
    return 0;
}
習(xí)題3-5 謎題UVa227

首先解決的是二維數(shù)組的輸入尚粘,考慮到會有空格在輸入里择卦,剛開始嘗試的是getchar實現(xiàn),但是要循環(huán)讀入時郎嫁,要控制換行\(zhòng)n的讀入秉继,存儲空格的位置。而且這個題目有坑泽铛,就在題目中賦值的測試數(shù)據(jù)尚辑,如果空格在最右邊的話,拖拽復(fù)制的話根本沒有復(fù)制到空格盔腔,放在控制臺直接驗證會出錯腌巾,但依據(jù)題意來說,其實是有空格的铲觉。

紫書上說gets函數(shù)已經(jīng)被廢棄了澈蝙,但是從這道題發(fā)現(xiàn)

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char* argv[])
{
    int count=1;
    bool line = false;
    
    while(1){
        char init[5][5];
        char c;
        
        int puzzle=1;
        int i,j;
        int bi,bj;
        gets(init[0]);
        if(init[0][0] == 'Z')return 0;
        for(i=1;i<5;i++){
            gets(init[i]);
        }
        for(i=0;i<5;i++){
            for(j=0;j<5;j++){
                c = init[i][j];
                if(c == ' ') {
                    bi = i;bj = j;
                    i = 5;j=5;
                }
            }
        }
        
        char command [1000];
        bool valid = true;
        bool exit_koro = false;

        while ( !exit_koro && gets (command)) {

            for ( int i = 0; command [i] != 0; i++ ) {

                if ( command [i] == '0' || !valid ) {
                    exit_koro = true;
                    break;
                }
                switch (command [i]) {
                case 'A' :
                    if ( bi == 0 )
                        valid = false;
                    else {
                        init [bi] [bj] = init [bi - 1] [bj];
                        init [bi - 1] [bj] = ' ';
                        bi--;
                    }
                    break;

                case 'B' :
                    if ( bi == 4 )
                        valid = false;
                    else {
                        init [bi] [bj] = init [bi + 1] [bj];
                        init [bi + 1] [bj] = ' ';
                        bi++;
                    }
                    break;

                case 'R' :
                    if ( bj == 4 )
                        valid = false;
                    else {
                        init [bi] [bj] = init [bi] [bj + 1];
                        init [bi] [bj + 1] = ' ';
                        bj++;
                    }
                    break;

                case 'L' :
                    if ( bj == 0 )
                        valid = false;
                    else {
                        init [bi] [bj] = init [bi] [bj - 1];
                        init [bi] [bj - 1] = ' ';
                        bj--;
                    }
                    break;
                }
            }
        }

        if ( line )
            printf ("\n");
        line = true;

        printf ("Puzzle #%d:\n", count++);

        if ( valid ) {
            for ( int i = 0; i < 5; i++ ) {
                printf ("%c %c %c %c %c\n", init [i] [0], init [i] [1],
                        init [i] [2], init [i] [3], init [i] [4]);
            }
        }

        else
            printf ("This puzzle has no final configuration.\n");
    }
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市撵幽,隨后出現(xiàn)的幾起案子灯荧,更是在濱河造成了極大的恐慌,老刑警劉巖盐杂,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逗载,死亡現(xiàn)場離奇詭異,居然都是意外死亡链烈,警方通過查閱死者的電腦和手機厉斟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來强衡,“玉大人擦秽,你說我怎么就攤上這事′銮冢” “怎么了感挥?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長越败。 經(jīng)常有香客問我触幼,道長,這世上最難降的妖魔是什么究飞? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任置谦,我火速辦了婚禮堂鲤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘媒峡。我一直安慰自己筑累,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布丝蹭。 她就那樣靜靜地躺著,像睡著了一般坪蚁。 火紅的嫁衣襯著肌膚如雪奔穿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天敏晤,我揣著相機與錄音贱田,去河邊找鬼。 笑死嘴脾,一個胖子當(dāng)著我的面吹牛男摧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播译打,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼耗拓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奏司?” 一聲冷哼從身側(cè)響起乔询,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎韵洋,沒想到半個月后竿刁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡搪缨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年食拜,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片副编。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡负甸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出痹届,到底是詐尸還是另有隱情惑惶,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布短纵,位于F島的核電站带污,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏香到。R本人自食惡果不足惜鱼冀,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一报破、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧千绪,春花似錦充易、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瑞妇,卻和暖如春稿静,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辕狰。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工改备, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蔓倍。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓悬钳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偶翅。 傳聞我的和親對象是個殘疾皇子默勾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容