紫书第三章课后习题题解(超详细!!!)

蛇形填数

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int a[1000][1000];
int main()
{

    int t;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int tot = 0;
        memset(a, 0, sizeof(a));
        int x =0, y = n-1;
        x =0;
        a[0][n-1] =1;
        tot = 1;
        while(tot < n*n)
        {
            while(x+1<n && !a[x+1][y])   a[++x][y] =++tot;
            while(y-1>=0 && !a[x][y-1])  a[x][--y] = ++tot;
            while(x-1>=0 && !a[x-1][y])  a[--x][y] = ++tot;
            while(y+1< n && !a[x][y+1])  a[x][++y] = ++tot;
        }
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
            {
                cout<<a[i][j]<<"   ";
            }
            cout<<endl;
        }
        cout<<endl;
    }
    return 0;
}9

环状序列 Uva 1584

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int les(const 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 t;
    char s[100];
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s", s);
        int ans = 0;
        int n = strlen(s);
        for(int i = 1; i<n; i++)
            if(les(s, i, ans)) ans = i;
        for(int i = 0; i<n; i++)
            putchar(s[(i+ans) % n]);
        cout<<endl;

    }
    return 0;
}
总结

这道题的循环用得非常好,取余这个操作也非常好。

得分 Score Uva 1585

总结:基础循环的应用。

#include<iostream>
#include<cstring>
using namespace std;
int len;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        char s[100];
        int vis[100];
        memset(vis, 0, sizeof(vis));
        scanf("%s",s);
        len = strlen(s);
        int sum = 0;
        int flag = 0;
        for(int i = 0; i < len; i++)
        {
            if(s[i] == 'X')
            {
                flag = 0;
            }
            else
            {
                flag ++;
                sum += flag;
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}

分子量 Molar Mass Uva 1586

总结:这道题有点小麻烦,要看原子后面的个数有多少个,好的是这道题没括号。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[100010];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(s, -1, sizeof(s));
        scanf("%s", s);
        double sum = 0;
        double tp;
        for(int i = 0; s[i] != -1; i++)
        {
            if(s[i] == 'C')
            {
                tp = 12.01;
                int cnt = 0;
                while(s[i+1] >='0' && s[i+1] <= '9')
                {
                    cnt = cnt*10+s[i+1]-'0';
                    i++;
                }
                if(cnt  == 0)
                {
                    sum += tp;
                }
                else sum += tp *cnt;
            }
            else if(s[i] == 'H')
            {
                tp = 1.008;
                int cnt = 0;
                while(s[i+1] >='0' && s[i+1] <= '9')
                {
                    cnt = cnt*10+s[i+1]-'0';
                    i++;
                }
                if(cnt  == 0)
                {
                    sum += tp;
                }
                else sum += tp *cnt;
            }
            else if(s[i] == 'O')
            {
                tp = 16.00;
                int cnt = 0;
                while(s[i+1] >='0' && s[i+1] <= '9')
                {
                    cnt = cnt*10+s[i+1]-'0';
                    i++;
                }
                if(cnt  == 0)
                {
                    sum += tp;
                }
                else sum += tp *cnt;
            }
            else if(s[i] == 'N')
            {
                tp = 14.01;
                 int cnt = 0;
                while(s[i+1] >='0' && s[i+1] <= '9')
                {
                    cnt = cnt*10+s[i+1]-'0';
                    i++;
                }
                if(cnt  == 0)
                {
                    sum += tp;
                }
                else sum += tp *cnt;
            }
        }
       printf("%.3f\n", sum);
    }
    return 0;
}

数数字 Digit Counting Uva 1225

总结:这道题搞一个vis数组就行。

#include<iostream>
#include<cstring>
using namespace std;
int s[15];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        memset(s, 0, sizeof(s));

        for(int i = 1; i <= n; i++)
        {
            int tp = i;
            while(tp)
            {
                s[tp % 10]++;
                tp /= 10;
            }
        }
        for(int i = 0; i<=9; i++)
        {

            if(i)
            cout<<" "<<s[i];
            else
                cout<<s[i];
        }
        cout<<endl;
    }
    return 0;
}

周期串 Periodic Strings Uva 455

总结:这道题用kmp的nex数组来进行操作就好,不知道kmp有什么用处的可以到我的另一篇博客中查看。
kmp超详细题单以及用法

#include <cstdio>
#include<iostream>
#include <cstring>
using namespace std;
int n;
char str[100];
int nxt[100];
int len;

void getNext()
{
    int i = 0, j = -1;
    nxt[0] = -1;
    while (i != len){
        if (j == -1 || str[i] == str[j]){
            nxt[++i] = ++j;
        }
        else
            j = nxt[j];
    }
}

int main()
{
    scanf("%d", &n);
    while (n--){
        scanf("%s", str);
        len = strlen(str);
        getNext();
        if (len % (len - nxt[len]) == 0)
            printf("%d\n", len - nxt[len]);
        else
            printf("%d\n", len);
        if (n)
            printf("\n");
    }
    return 0;
}

纵横字谜的答案 Crossword Answers Uva 232

总结:这道题要注意看题,注意一开始要把数组处理好。

#include<iostream>
#include<cstring>
using namespace std;
char a[100][100];
int vis[100][100];
int lrow, lcolumn;
int main()
{
    int flag = 0;
    while(cin>>lrow && lrow)
    {
        cin>>lcolumn;
        for(int i = 0; i < lrow; i++)
            for(int j = 0; j < lcolumn; j++)
            cin>>a[i][j];
        memset(vis, 0 , sizeof(vis));
        int c = 0;
        for(int i = 0; i< lrow;i++)
        {
            for(int j = 0; j < lcolumn; j++)
            {
                if(i == 0 && a[i][j] != '*')
                {
                    c++;
                    vis[i][j] = c;
                }
                else
                {
                    if(j == 0 && a[i][j] != '*')
                        vis[i][j] = ++c;
                    else if(a[i][j] != '*' && a[i][j-1] == '*')
                        vis[i][j] = ++c;
                    else if(a[i][j] != '*' && a[i-1][j] == '*')
                        vis[i][j] = ++c;
                }
            }
        }
        if(flag )
            cout<<"\n";
        cout<<"puzzle #"<<++flag<<":\n";

        int tp = 0;

        cout<<"Across"<<endl;
        for(int i = 0; i< lrow; i++)
        {
            for(int j = 0; j < lcolumn; j++)
            {
                 if(tp == 0 && a[i][j] !='*')
                 {
                     printf("%3d.", vis[i][j]);
                     cout<<a[i][j];
                     tp =1;

                 }
                 else if(a[i][j] == '*' && tp == 1)
                 {
                     tp = 0;
                     cout<<endl;
                 }
                 else if(tp == 0 && a[i][j] =='*')
                 {
                     continue;
                 }
                 else if(tp == 1 && a[i][j] !='*')
                 {
                     cout<<a[i][j];

                 }
            }
            if(tp == 1)
                cout<<endl;
            tp = 0;
        }

        tp = 0;

        cout<<"Down"<<endl;
        char tmp[100][100];
        memset(tmp, 0, sizeof(tmp));
        int tpj = 0;
        int g;
        for(int j = 0; j< lcolumn; j++)
        {
            for(int i = 0; i < lrow; i++)
            {
                 if(tp == 0 && a[i][j] !='*')
                 {
                    g = vis[i][j];
                    tmp[g][tpj++] = a[i][j];
                    tp =1;

                 }
                 else if(a[i][j] == '*' && tp == 1)
                 {
                     tp = 0;
                    tpj = 0;
                 }
                 else if(tp == 0 && a[i][j] =='*')
                 {
                     tpj = 0;
                     continue;
                 }
                 else if(tp == 1 && a[i][j] !='*')
                 {

                     tmp[g][tpj++]  = a[i][j];
                 }

            }
            tpj = 0;
            tp = 0;

        }
        for(int i = 0; i<100; i++)
        {
            if(tmp[i][0] != 0)
            {
                printf("%3d.", i);
                for(int j = 0; tmp[i][j] !=0;j++)
                {
                    cout<<tmp[i][j];
                }
                 cout<<endl;
            }


        }

    }
    return 0;
}

DNA 序列 DNA Consensus String Uva 1368

总结:这道题用到了一个贪心的策略,就是在几个序列中出现最多的字符就是我们需要的那一个字符,如果所有字符出现的次数都一样,那就任选一个。

#include<iostream>
#include<cstring>
using namespace std;
char a[50][1010];
int vis[10];
int tmp[1020];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int len;
        int times;
        cin>>times>>len;
        for(int i = 0; i<times; i++)
        {
            scanf("%s", a[i]);
        }

        //ACGT;
        int sum = 0;
        for(int i = 0; i<len;i++)
        {

            memset(vis, 0, sizeof(vis));
            for(int j = 0; j<times; j++)
            {
                if(a[j][i] == 'A')
                {
                    vis[0]++;
                }
                else if(a[j][i] == 'C')
                {
                    vis[1]++;
                }
                else if(a[j][i] == 'G')
                {
                    vis[2]++;
                }
                else if(a[j][i] == 'T')
                {
                    vis[3]++;
                }
            }
            int maxn = vis[0];
            int tpi = 0;
            for(int z = 1; z<4;z++)
            {
                if(maxn < vis[z])
                {
                    maxn = vis[z];
                    tpi = z;
                }
            }
            tmp[i] = tpi;

            for(int p = 0; p<4;p++)
            {
                if(p != tpi)
                {
                    sum += vis[p];
                }
            }
        }
        for(int i = 0; i<len;i++)
        {
            if(tmp[i] == 0)
                cout<<"A";
            if(tmp[i] == 1)
                cout<<"C";
            if(tmp[i] == 2)
                cout<<"G";
            if(tmp[i] == 3)
                cout<<"T";
        }
        cout<<endl;
        cout<<sum<<endl;
    }
    return 0;
}

循环小数 Repeating Decimals Uva 202

总结:只要余数有重复的,说明开始循环。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[10000000];
int vis[10000000];
int main()
{
    int bc,cs;
    int bb, cc;
    while(cin>>bb>>cc)
    {
        bc = bb;
        cs = cc;
        int len = 0;
        int zs = bc /cs;
        bc = bc % cs;
        memset(vis, -1 ,sizeof(vis));
        bc *= 10;
        vis[bc] = 0;
        a[len++] = bc / cs;
        bc  = bc % cs;
        int cnt;
        while(1)
        {
            bc*=10;
            if(vis[bc] != -1)
            {
                //cout<<len-vis[bc]<<endl;;
                cnt = len - vis[bc];
                break;
            }
            vis[bc] = len;
            a[len++] = bc / cs;
            bc = bc % cs;
        }
        printf("%d/%d = %d.",bb,cc,zs);
        for(int i = 0; i<vis[bc]; i++)
            cout<<a[i];
        cout<<"(";
        if(cnt <50)
        for(int i = 0;i<cnt;i++)
            cout<<a[vis[bc]+i];
        else
        {
            for(int i = 0;i<50;i++)
            cout<<a[vis[bc]+i];
            cout<<"...";
        }
        cout<<")\n";
        printf("   %d = number of digits in repeating cycle\n\n", cnt);
    }
    return 0;
}

子序列 All in All Uva 10340

总结:有点相当然了,一开始写得有点简单,wa了几次,其实不难,中间条件写好就行,vis数组是存是否匹配。

#include<iostream>
#include<cstring>
using namespace std;
char s[100000];
char a[100000];
int vis[100000];
int main()
{
    while(scanf("%s",s) != EOF)
    {

        scanf("%s",a);
        int slen = strlen(s);
        memset(vis,0 ,sizeof(vis));
        int alen = strlen(a);
        int j = 0;
        int i = 0;
        for( i; i <slen; )
        {
            for(j; j < alen; j++)
            {
                 if(s[i] == a[j])
                 {
                     vis[i] = 1;
                     j++;
                     i++;
                     break;
                 }
            }
            if(j == alen )
                break;
        }

        if(vis[slen-1] == 1)
            cout<<"Yes\n";
        else
            cout<<"No\n";
    }
    return 0;
}

盒子 Box Uva 1587

总结:长方体只有长宽高三个属性,只要把输入处理好一比较就能得出答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node{
    int x,y;
};

bool cmp(Node a, Node b)
{
    return a.x != b.x ? a.x <b.x :a.y > b.y;

}
bool isok(Node a[6])
{
    if(a[0].x != a[1].x ||a[2].x != a[3].x || a[4].x != a[5].x ||a[0].y != a[1].y || a[2].y != a[3].y|| a[4].y != a[5].y)
        return false;
    if(a[0].x != a[2].x || a[0].y != a[4].y ||a[2].y != a[4].x)
        return false;
    return true;
}
int main()
{
    Node a[6];
    int x, y;
    while(scanf("%d%d", &x,&y) != EOF)
    {
        a[0].x = x;
        a[0].y = y;
        if(a[0].x > a[0].y)
            swap(a[0].x, a[0].y);
        for(int i = 1; i<6; i++)
        {
            scanf("%d%d", &x, &y);
            a[i].x = x;
            a[i].y = y;
            if(a[i].x > a[i].y)
                swap(a[i].x, a[i].y);
        }
        sort(a,a+6, cmp);
        if(isok(a))
        {
			printf("POSSIBLE\n");
		}
		else{
			printf("IMPOSSIBLE\n");
		}
    }
    return 0;
}

换抵挡装置 Kickdown uva 1588

总结:这道题的关键是有左移和右移,如果没考虑到这个的话,肯定wa,左移和右移的代码也非常的简单,一个双重循环就行。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char c[200];
char d[200];
int solve(char a[200], char b[200])
{
    int alen = strlen(a);
    int blen = strlen(b);
    int i  = 0, j= 0;
    int flag = 0;
    int len ;
    for(i ; i<alen; )
    {
        for(j ; j<blen;)
        {
            int tpa = a[i+j] - '0';
            int tpb = b[j] - '0';

            if(tpa + tpb <=  3)
            {
                j++;
            }
            else if(tpa + tpb > 3)
            {
                flag++;
                i = flag;
                j = 0;
            }

            if(i +j >= alen)
            {
                return flag + blen;
            }
        }
       
        if(i == alen)
        {
            len = flag + blen;
            return len;
        }
        else if(j == blen)
        {
            len = alen;
            return len;
        }
    }
    return 0;
}
int main()
{
    while(scanf("%s", c)!=EOF)
    {
        scanf("%s",d);
        int sy, xy;
        xy = solve(c,d);
        sy = solve(d,c);
        cout<<min(xy,sy)<<endl;
    }
    return 0;
}

浮点数 Floating - Point Numbers Uva 11809

搞不是很定,后面再补题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值