算法自学练习 自用(基础)

1、近似计算:PI/4,直到最后一项小于pow(10,-6);

#include <iostream>
#include <cmath>

using namespace std;
#define PI 3.1415926

int main() {
    float sum = 0;
    int n = 1;
    int temp;
    while (sum <= PI) {
        sum += 1.0 / n * pow(-1, n + 1);
        if (1.0/ n <= pow(10, -6))break;
        n += 2;
    }
    temp=(1.0/n)*pow(10,6);
    cout << floor(temp+0.5)*pow(10,-6);
    return 0;

}

总结:floor()函数的使用是向下取整,+0.5就可以四舍五入。

2、阶乘之和:计算S=1!+…+n!的末六位

#include <iostream>
#include <cmath>

using namespace std;

int digui(int i){
    if(i==1)return 1;
    return i*digui(i-1);
}

int main() {
    int sum=0;
    int n;
    int temp;
    cin>>n;
    for(int i=1;i<=n;i++){
        sum+=digui(i);
    }
    temp=sum%1000000;
    cout<<temp;
    return 0;

}

总结:递归要在函数内找到一个出口这次i==1就是它的出口。

3、数据统计:利用while(cin>>x)来进行重复输入。然后利用EOF来结束并运行程序。

#include <iostream>
#include <string>
#include <iomanip>

using  namespace std;
#define INF 1000000

int main(){
    int x,n=0,min=INF,max=-INF,s=0,kcase=0;
    while(cin>>n&&n){
        int s=0;
        for(int i=0;i<n;i++){
            cin>>x;
            if(x<min)min=x;
            if(x>max)max=x;
            s+=x;
        }
        if(kcase)cout<<endl;
        cout<<"Case"<<++kcase<<":"<<min<<" "<<max<<" "<<setiosflags(ios::fixed|ios::showpoint)<<setprecision(3)<<(double)s/n<<endl;
    }
    return 0;
}

总结:较为新颖的地方就是用到了里面的

setiosflags(ios::fixed|ios::showpoint)<<setprecision(3)

标题来保存小数点后三位,并保存小数点后的0;

4、水仙花数

#include <iostream>
#include <string>
#include <iomanip>

using  namespace std;
#define INF 1000000

int main(){
    int a,b,c,sum=0;
    for(int i=100;i<=999;i++){
        a=i/100;
        b=(i/10)%10;
        c=i%10;
        sum=pow(a,3)+pow(b,3)+pow(c,3);
        if(sum==i)cout<<i<<" ";
    }
    return 0;
}

5、韩信点兵:(待优化)

#include <iostream>
#include <string>


using  namespace std;

int main(){
    int a,b,c,kcase=1;
    while (cin>>a&&cin>>b&&cin>>c){
        for(int i=10;i<=100;i++){
            if((i-a)%3==0&&(i-b)%5==0&&(i-c)%7==0){
                cout<<"Case"<<kcase<<":"<<i;
                break;
            }
            if(i==100){
                cout<<"Case"<<kcase<<":"<<"No answer";
            }
        }
        kcase++;
    }
    return 0;
}

6、倒三角形:通过建立坐标轴和利用二维数组进行相应绘画。

#include <iostream>
#include <string>


using namespace std;
char a[41][41];

void draw(int posx, int posy, int n) {
    for (int i = 0; i < n; i++) {
        a[posx][posy+i] = '#';
//        cout<<"第"<<i+1<<"层";
        for(int j=1;j<i+1;j++){
            a[posx-j][posy+i]='#';
            a[posx+j][posy+i]='#';
//            cout<<j;
        }

    }
}
void printf(int posx,int n){
    for (int i =n-1; i >=0 ; --i) {
        for (int j=posx-n+1;j<posx+n;j++) {
            cout<<a[j][i];
//            cout<<endl;

        }
        cout<<endl;

    }
}

int main() {
    memset(a,' ',sizeof (a));
    int posx=21,posy=0,n;
    cin>>n;
    draw(posx,posy,n);
    printf(posx,n);
    return 0;
}

总结:

1、memset(数组名,“ ”,sizeof(数组名)),进行二维数组初始化。

2、建立全局数组变量就可以在函数内直接修改。

3、在建立二维坐标轴的时候要搞清楚谁是x,谁是y,否则无论打印还是输出都不好弄。

7、子序列的和:关键是在考整数溢出的问题,int的范围-2147483648 ~ 214748364,而当n=655360是乘方后将达到12位,容易造成溢出。

#include <iostream>
#include <string>
#include<cmath>
#include <iomanip>


using namespace std;
#define INF 100000


int main() {
   long long n, m, kcase = 1;
    float sum = 0;
    while (cin >> n && cin >> m && n != 0 & m != 0) {
        for ( n; n <= m; ++n) {
            n*=INF;
            n/=INF;
            sum += pow(pow(n,2),-1);
        }
        cout << "Case " << kcase << ":" << setiosflags(ios::fixed | ios::showpoint) << setprecision(5) << sum;
        kcase++;
        sum=0;
    }

    return 0;
}

总结:

1、应该考虑到除不尽的小数,所以要对整数进行保留五位小数点的操作,即一乘一除。

2、四舍五入的背诵:头文件是:iomanip,
函数内容是<<setiosflags(ios::fixed|ios::showpoint)<<setprecision(n)

8、分数化小数:主要就是两个int类型的相乘的话就要*1.0化成浮点型的。

#include <iostream>
#include <string>
#include<iomanip>




using namespace std;


int main() {
    int a,b,c,kcase=1;
    float s;
    while(cin>>a&&cin>>b&&cin>>c&&a!=0&&b!=0&&c!=0){
        s=1.0*a/b;
        cout<<"Case "<<kcase<<":"<<setiosflags(ios::fixed|ios::showpoint)<<setprecision(c)<<s;
        kcase++;
    }

    return 0;
}

总结:

四舍五入的函数就是好用;

9、排列:用0-9组成3个三位数字,且每个数字恰好用一次,同时abc=def=ghi=1:2:3;

#include <iostream>
#include <string>

using namespace std;

int vis[10]={0};

void getnum(int list){
    int a=list/100;
    int b=(list/10)%10;
    int c=list%10;
    vis[a]+=1;
    vis[b]+=1;
    vis[c]+=1;
}


int main() {
    int abc,def,ghi;
    for(int i=123;i<=329;i++){
        abc=i;
        def=i*2;
        ghi=i*3;
        getnum(abc);
        getnum(def);
        getnum(ghi);
        for(int j=1;j<10;j++){
            if(vis[j]==0)break;
            if(j==9)cout<<abc<<" "<<def<<" "<<ghi<<endl;
        }
        memset(vis,0,sizeof (vis));
    }


    return 0;
}

总结:

关键在于利用数组来记录数字的使用情况,同样是利用到全局数组来进行记录。

还有就是利用menset()函数来重复初始化数组。

10、for循环的小细节:

#include <iostream>
#include <string>

using namespace std;



int main() {
    int n;
    cin>>n;
    for(int i=2;i<=2*n;i+=2){
        cout<<i<<endl;
    }
    return 0;
}

在for(;;i+=2)才可以,如果只是i+2,就会陷入死循环。

11、开灯问题:有n盏灯编号1~n,第一个人全开了,后面的人按自己编号的倍数开关灯。

#include <iostream>
#include <string>

using namespace std;
#define maxon 1010
int lantern[maxon];

void turnOff(int n, int k) {
    memset(lantern, 0, sizeof lantern);
    for (int i = 2; i <= k; i++) {
        for (int j = 1; j <= n; j++) {
            if (j % i == 0) {
                if (lantern[j] == 0)
                    lantern[j] = -1;
                else lantern[j] = 0;
            }
        }
    }
    for (int h = 1; h <= n; h++) {
        if (lantern[h] == 0)cout << h << " ";
    }
}

int main() {
    int n, k;
    cin >> n >> k;
    turnOff(n, k);
    return 0;
}

总结:

1、memset()在int方面只能弄-1和0,不能弄1,除非是字符‘1’。且它的头文件名是<string>

2、int a[maxon]表示声明了一个包含maxon个整型变量的数组,其中maxon只能是常数,不能是变量。

3、定义数组的时候可以定义在main()外面这样数组才可以开的很大,放在里面容易异常退出。

4、数组交换可以用memcpy(b,a,sizeof(a))表示把a数组复制到b中。

12、蛇形填数:下左上右在二维数组里面填数。

#include <iostream>
#include <string>
#include <cmath>

using namespace std;
#define maxn 1010
int snakeFill[maxn][maxn];




int main() {
    int n,x,y,count=2;
    memset(snakeFill,0,sizeof (snakeFill));
    cin>>n;
    snakeFill[x=0][y=n-1]=1;
    while (count<n*n){
        while(1+x<n&&!snakeFill[x+1][y])snakeFill[++x][y]=count++;
        while(y-1>=0&&!snakeFill[x][y-1])snakeFill[x][--y]=count++;
        while(x-1>=0&&!snakeFill[x-1][y])snakeFill[--x][y]=count++;
        while(y+1<n&&!snakeFill[x][y+1])snakeFill[x][++y]=count++;
    }
    for(int i=0;i<n;i++){
        for (int j = 0; j < n; ++j) {
            if(snakeFill[i][j]<10)cout<<snakeFill[i][j]<<" "<<"\t";
            else
                cout<<snakeFill[i][j]<<"\t";
        }
        cout<<endl;
    }
    return 0;
}

总结:

1、用while循环来做判断条件,与此同时利用++来更改变量值,这是我要学习的地方。

14、竖式输出:输入一个数字集合,然后去找三位数乘两位数的算式,且这些数字属于特定集合,如果符合条件就排版输出,并在最后输出解的总数。

#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>

using namespace std;


int main() {
    char s[20], buf[99];
    cin >> s;
    int x, y, z, count = 0;
    for (int abc = 100; abc < 999; ++abc) {
        for (int i = 10; i < 99; ++i) {
            x = abc * (i % 10);
            y = abc * (i / 10);
            z = abc * i;
            sprintf(buf, "%d%d%d%d%d", abc, i, x, y, z);
            int ok = 1;
            for (int j = 0; j < strlen(buf); j++) {
                if (strchr(s, buf[j]) == nullptr)ok = 0;
            }
            if (ok) {
                cout << "<" << ++count << ">" << endl;
                cout << "  " << abc << endl;
                cout << "x  " << i << endl;
                cout << "-----" << endl;
                cout << setw(5) << setfill(' ') << x << endl;
                cout << setw(4) << setfill(' ') << y << endl;
                cout << "-----" << endl;
                cout << setw(5) << setfill(' ') << z << endl;
            }
        }
    }
    cout << '\n' << "The number of solutions =" << count;
    return 0;
}

总结:

1、新学的sprintf()函数来进行数组赋值,格式为:sprintf(buf, "%d%d%d%d%d", abc, i, x, y, z);

2、strlen()函数获取数组的实际长度(包括一个‘\0’),格式为:strlen(buf)

3、strchr()函数用于单个字符的查找,返回nullptr,true;格式为:

for (int j = 0; j < strlen(buf); j++) {
                if (strchr(s, buf[j]) == nullptr)ok = 0;
            }

4、setw()函数,用于保留几位数字,不够的setfill()函数来凑,头文件为<iomanip>,
格式为:cout << setw(5) << setfill(' ') << x << endl;

15、Tex中的引号:将论文中的‘ “” ’改成``

#include <iostream>
#include <string>


using namespace std;

int main() {
    int c,q=1;
    string s;
    while((c=getchar())!=EOF){
        if(c=='"'){
            s=q ? "``":"''";
            cout<<s;
            q=!q;
        }
        else{
            cout<<(char)c;
        }
    }
    return 0;
}

总结:

1、在利用while循环加getchar()进行单个字符的获取和连续输入

2、利用?:来判断选择左右``,同时用q=!q;来进行调换。

3、注意点:因为c得到的int型的,输出时记得转换成char型

16、字符纠正:把在键盘上往右输错的字符给纠正出来不能出界。

#include <iostream>
#include <string>


using namespace std;

char arr[]="`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";


int main() {
    int c,i;
    while((c=getchar())!=EOF){
        if(c==32)putchar(char(32));
        for(i=1;arr[i]&&arr[i]!=c;i++);
        if(arr[i]==c)putchar((char)arr[i-1]);
        else putchar((char)arr[i]);
    }
    return 0;
}

总结:

1、像这种可以每输入一个字符就可以输出一个字符的程序,可以考虑使用getchar()putchar()函数。

2、利用常量数组,可以大大方便代码的使用,尤其是考虑到这种有相邻关系的题目。

3、个人感觉这个代码还有一个精细的地方就是利用for循环,来进行无语句的搜寻。

17、回文词:输入一个字符串判断它是否为回文串和镜像串。

#include <iostream>
#include <string>


using namespace std;

char arr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
char Arr[] = "A000300HIL0JM0O0002TUVWXY51SE0Z0080";
char temp[99];
char temp2[99];
char temp3[99];


int main() {
    int c, i, count = 0, sign = 1, sign1 = 1;
    while ((c = getchar()) != EOF) {
        temp3[count] = (char) c;
        temp2[99 - count] = (char) c;
        for (i = 0; arr[i] && arr[i] != c; i++);
        if (arr[i])temp[count] = Arr[i];
        count++;
        for (int j = 0; j < count + 1; j++) {
            if (temp[j] != temp3[j]) {
                sign = 0;
            }
            if (temp3[j] != temp2[99 - count + j])sign1 = 0;
        }
    }
    for (int k = 0; k < count + 1; k++) {
        cout << temp3[k];
    }
    if (sign && sign1) {
        cout << "--is a mirrored palindrome.";
    }
    if (!sign1) {

        cout << "--is not a palindrome.";
    }
    if (sign1) {
        cout << "--is a regular palindrome.";
    }
    if (sign) {
        cout << "--is a mirrored string.";
    }
    return 0;
}

总结:

1、这边利用到了常量数组来进行对应判断。

18、得分:在这里插入图片描述

#include <iostream>
#include <string>
#define INF 100000



using namespace std;


int main() {
    int c,s=0,count=0;
    while((c=getchar())!='#'){
        if(c=='O'){
            count++;
            s+=count;
        }
        else if(c=='X'){
            count=0;
        }
    }
    cout<<s;
    return 0;
}

19、在这里插入图片描述

#include <iostream>
#include <string>
#define maxn 1010

float a[4]={12.01,1.008,16.00,14.01};
float arr[maxn];


using namespace std;


int main() {
    double s=0;
    int c;
    int i=0;
    memset(arr,0,sizeof (arr));
    while((c=getchar())!='#'){
        switch (c) {
            case 'C':
                arr[i]=a[0];
                s+=a[0];
                break;
            case 'H':
                arr[i]=a[1];
                s+=a[1];
                break;
            case 'O':
                arr[i]=a[2];
                s+=a[2];
                break;
            case 'N':
                arr[i]=a[3];
                s+=a[3];
                break;
            default:
                 c=c-'0';
                 s=s+arr[i-1]*1.0*(c-1);
                break;
        }
        i++;
    }
    cout<<s;
    return 0;
}

总结:

1、getchar()返回的是int类型,而‘N’也是int类型的Ascll码。

2、getchar()返回的int类型变量可以直接使用,但是其值是ascll码。

20、数数字,把整数写在一起。数0-9各出现多少次。

#include <iostream>
#include <string>

#define maxn 1010

int arr[10];

using namespace std;

int main() {
    int c;
    memset(arr, 0, sizeof(arr));
    while ((c = getchar()) != '#') {
        c = c - '0';
        arr[c] += 1;
    }
    for (int i = 0; i < 10; i++) {
        cout << arr[i] << " ";
    }
    return 0;
}

总结

1、利用的数字与数组的对应关系。来进行加数。

21、猜字符:输入一段字符,并输入另一段字符,进行逐个字符校验。

#include <iostream>
#include <string>

using namespace std;

#define maxn 1010
char s[maxn], computer[maxn];
int win, lose;
int left1, chance;

void guess(char a){
    int bad=1;
    for(int i=0;i<strlen(computer);i++){
//        cout<<a;
        if(a==computer[i]){
            bad=0;
            left1--;
            computer[i]=' ';
        }
    }
    if(bad)--chance;
    if(!left1)win=1;
    if(!chance)lose=1;
}

int main() {
    int rnd;
    while(cin>>rnd&&rnd!=-1){
        cin>>computer;
        cin>>s;
        cout<<"Round"<<rnd<<":"<<endl;
        win=lose=0;
        left1=strlen(computer);
        chance=7;
        for (int i = 0; i <strlen(s) ; ++i) {
            guess(s[i]);
            if(win||lose)break;
        }
        if(win)cout<<"You win"<<endl;
        else if(lose)cout<<"You lost"<<endl;
        else cout<<"You chickened out"<<endl;
    }
    return 0;
}

总结:

1、利用全局变量来避免指针的传递。

2、采用全局变量来进行胜负的标志。利用整型变量的0,1来对结果进行划分。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值