近期题目归纳(2016.07.08)

近期简单题目归纳

UVA - 1585

题意:给一串由OX组成的字符串,根据X为 0 分,O为 1 分,当O连续多个时O的分数为它前面连续0的个数。
解法:统计连续O的个数就好啦。用一个标记变量tag来计算,遇到X时tag = 0,遇到一个O就对tag进行+1。到每个位置只要累加tag就好了。

#include<iostream>
#include <string>
#include<algorithm>
#include <cstdio>
using namespace std;
int n;
int main () {
    scanf("%d",&n);
    while (n) {
        n--;
        string s;
        int ans=0,tag=0;
        cin>>s;
        for (int i = 0;i < s.length(); i++) {
            if (s[i]=='O') tag++;
              else tag=0;
              ans+=tag;
        }
        cout<<ans<<endl;
    }
}

UVA-1225

题目描述的很清楚,循环1 to n,通过%和/把每个数组的各个数字都取出来,用一个数组来统计每个数字出现的次数。最后输出结果。

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
using namespace std;
int main () { 
    int n,a[13];
    scanf("%d",&n);
    while (n){
        n--;
        int c;
        scanf("%d",&c);
        for (int i = 0 ; i <= 9 ; i++ )
            a[i]=0;
        for (int i = 1; i <= c ; i++ ){
            int j = i;
            while (j){
                a[j%10]++;
                j/=10;
            }
        }
        for (int i = 0; i <= 8 ; i++)
            printf("%d ",a[i]);
        printf("%d\n",a[9]);
    }
}

UVA-455

题意:求字符串的最小循环长度。
解法:循环结长度肯定是字符串长度的一个约数。那么就可以循环i = 1 to length,当前i时length的一个约数时,判断是不是循环结。因为是从小到大循环,第一个满足的肯定时最小的。

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
using namespace std;
string s;
int n,ans;
int main () {
    scanf("%d",&n);
    while (n){
        n--;
        cin>>s;
        int l=s.length();
        s=" "+s;
        for (int k = 1; k <= l; k++)
            if ( l % k == 0){
                int tag=0;
                for (int i = k+1; i <= l ; i++)
                    if (s[i] != s[(i-1) % k +1]) {
                        tag=-1;
                        break;
                    }
                if (tag == 0){
                    ans=k;
                    break;
                }
            }
        printf("%d\n",ans);
        if (n) printf("\n");
    }
}

UVA-227

题意:给一个5*5的字符矩阵,然后会给若干个指令(ABLR)以数字0结尾。求经过这些指令操作之后的矩阵。若中间出现了越界,则输出 “This puzzle has no final configuration.”。
解法:这是一道纯模拟题,关键在于指令只说明以数字0作为结束标志,可能出现指令是多行的,中间有空格等等情况。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
const int t[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
char map[8][8];
int x,y,n,m;
int main () {
    freopen("xx.in","r",stdin);
    int num = 0;
    char c;
    int tag;
    scanf("%c",&map[1][1]);
    while (map[1][1]!='Z' && map[1][1]!='z'){
        if (map[1][1] == ' '){
            x=1;
            y=1;
        }
        for (int i = 1 ; i <= 5 ; i++)
            for (int j= (i ==1 ? 2 : 1) ; j <= 6 ; j++){
                scanf("%c",&map[i][j]);
                if (map[i][j] == ' ') {
                    x=i;
                    y=j;
                }
            }
        scanf("%c",&c);
        tag=0;
        while (c != '0'){
            n=m=0;
            if (c == 'A'){
                n = -1;
                m = 0;
            }
            if (c == 'B'){
                n = 1;
                m = 0;
            }
            if (c == 'L'){
                n = 0;
                m = -1;
            }
            if (c == 'R'){
                n = 0;
                m = 1;
            }
            if ( x + n < 1  ||  x + n > 5) tag=1;
            if ( y + m < 1  ||  y + m > 5) tag=1;
            scanf("%c",&c);     
            if (tag) continue ;
            map [x][y] = map [x+n][y+m];
            map [x+n][m+y] = ' ';
            x=x+n;
            y=y+m;
        }
        scanf("%c",&c);
        num++;
        cout<<"Puzzle #"<<num<<':'<<endl;
        if (!tag){
            for (int i = 1 ; i <= 5; i++) {
                for (int j = 1; j < 5; j++)
                    printf("%c ",map[i][j]);
                printf("%c\n",map[i][5]);
            }
        }else 
            cout<<"This puzzle has no final configuration."<<endl;
        scanf("%c",&map[1][1]);
        if (map[1][1] != 'Z') cout<<endl;
    }
}

UVA-232

解法:
给整个矩阵外面加一圈 * 。
首先对矩阵进行编号,一行一行往下,每一个前一个或上一个为 * 且本身不是 * 的都是一个单词的开端。
横着输出单词时就选择每一个前面是 * 且本身不是 * 的位置开始输出。
竖着输出单词时就选择每一个上面是 * 且本身不是 * 的位置开始输出。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,tag1,tag2,num;
char c[100][100];
int z[100][100];
int main () {
    freopen("xx.in","r",stdin);
    scanf("%d",&n);
    num = 0;
    while ( n ) {
        scanf("%d\n",&m);
        for (int i = 1;i <= n; i++)
            for (int j = 1 ; j <= m+1 ; j++)
                 scanf("%c",&c[i][j]);
        for (int i = 1; i <= n ; i++) c[i][m+1]=c[i][0]='*';
        for (int j = 1; j <= m ; j++) c[n+1][j]=c[0][j]='*';
        memset(z,0,sizeof(z));
        tag1=0;
        for (int i = 1; i <= n; i++ )
            for (int j = 1; j <= m ; j++)
              if ( c[i][j] != '*' )
                if (c[i-1][j] == '*'  || c[i][j-1] == '*'){
                    tag1++;
                    z[i][j]=tag1;
                }
        num++;
        cout<<"puzzle #"<<num<<':'<<endl;
        cout<<"Across"<<endl;
        for (int i = 1; i <= n ; i++){
            int j=1;
            while (j <= m ){
                if ( c[i][j] != '*'  &&  c[i][j-1] == '*' ){
                    printf("%3d.",z[i][j]);
                    while (c[i][j] != '*'){
                        printf("%c",c[i][j]);
                        j++;
                    }
                    cout<<endl;
                }
                j++;
            }
        }
        cout<<"Down"<<endl;
        for (int i = 1; i <= n ; i++ )
            for (int j = 1; j <= m; j++)
                if (c[i][j] != '*'  &&  c[i-1][j] == '*'){
                    printf("%3d.",z[i][j]);
                    int k=i;
                    while (c[k][j] != '*'){
                        printf("%c",c[k][j]);
                        k++;
                    }
                    cout<<endl;
                }
        scanf("%d",&n);
        if ( n ) cout<<endl;
    }
}

UVA-1368

题意:求一个长度为n的DNA序列,和已知的 m 个长度为n的DNA序列误差最小,并输出误差数。
解法:要误差最小,那么就取每一个位置上出现最多的那个碱基。题目要求多个解时取字典序最小的那个。在处理时可以按字典序来处理ACGT,比较时取 > ,这样就可以保证相同时取字典序小的了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
char s;
int n,m,sum[1200][5],tot;
int main () {
    freopen("xx.in","r",stdin);
    int t;
    scanf("%d",&t);
    while (t--){
        scanf("%d%d\n",&n,&m);
        tot=n*m;
        memset(sum,0,sizeof(sum));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m+1; j++) {
                scanf("%c",&s);
                if (s == 'A') sum[j][1]++;
                if (s == 'C') sum[j][2]++;
                if (s == 'G') sum[j][3]++;
                if (s == 'T') sum[j][4]++;
            }
            while (s != '\n') scanf("%c",&s);
        }
        for (int i = 1; i <= m; i++){
            int z=1;
            for (int j = 2; j <= 4; j++){
                if (sum[i][j] > sum[i][z]) z=j;
            }
            if (z == 1) printf("A");
            if (z == 2) printf("C");
            if (z == 3) printf("G");
            if (z == 4) printf("T");
            tot-=sum[i][z];
        }
        cout<<endl<<tot<<endl;
    }
}

UVA-10340

题意:求s能否通过对t进行更改获得。
解法:用两个变量 i , j 表示当前操作到 s 串和 t 串的位置。每次都对 j+1,当s[i] == t[i] 时就对 i+1。当结束的是哈 i >= s.length 就表示可以。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
string a,b;
int main () {
    freopen("xx.in","r",stdin);
    while (cin>>a>>b) {
        int i=0,j=0;
        while (i < a.length() && j < b.length()){
            if (a[i] == b[j]) i++;
            j++;
        }
        if (i >= a.length()) cout<<"Yes"<<endl;
         else cout<<"No"<<endl;
    }
}

UVA-1587

题意:给6个矩形的长宽,求这6个矩形是否能拼成一个长方体。
解法:要想拼成长方体就要想想有什么约束条件。
1、每个面都要找到一个和它相同的面
2、不同长度的边最多有3种,且每种出现的次数是4的倍数

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int t[50],lt,z[50],a[8],b[8];
void check (int x) {
    for (int i = 1; i <= lt; i++)
        if (t[i] == x){
            z[i]++;
            return ;
        }
    lt++;
    t[lt]=x;
    z[lt]=1;
}
void ans(){
    if (lt > 3) {
        cout<<"IMPOSSIBLE"<<endl;
        return ;
    }
    for (int i = 1; i <= lt; i++)
        if (z[i] % 4 != 0) {
            cout<<"IMPOSSIBLE"<<endl;
            return ;
        }
    for (int i = 1; i <= 6; i++){
        int k=1;
        for (int j = 1; j <= 6; j++)
            if (i != j && a[i] == a[j]  &&  b[i] == b[j]){
                k=0;
                break;
            }
        if (k) {
            cout<<"IMPOSSIBLE"<<endl;
            return ;
        }
    }
    cout<<"POSSIBLE"<<endl;
}

int main () {
    freopen("xx.in","r",stdin);
    while (cin>>a[1]>>b[1]){
        lt=0;
        check(a[1]);
        check(b[1]);
        if (b[1] < a[1]){
            int k=a[1];
            a[1] = b[1];
            b[1] = k;
        }
        for (int i = 2; i <= 6; i++){
            cin>>a[i]>>b[i];
            check(a[i]);
            check(b[i]);
            if (a[i] > b[i]) {
                int k=a[i];
                a[i]=b[i];
                b[i]=k;
            }
        }
        ans();
    }
}

UVA-1588

题意:给两块由高度为1或2的齿轮链,求用多长的高度为3的齿轮链可以装下给定的两个齿轮链。
解法:从第一个位置开始枚举,判断另一个能不能放上来,第一个能放上来的位置和被枚举的链长度中取最打一个。然后两个都枚举完取最小的那个,就是答案。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
string s1,s2;
int l1,l2;
bool check1 (int x) {
    for (int i = 0; i <= l2  &&  x+i <= l1; i++)
        if (s2[i] == '2' && s1[x+i] == '2')
            return false;
    return true;
}
bool check2 (int x) {
    for (int i = 0; i <= l1  &&  x+i <= l2; i++)
        if (s1[i] == '2'  &&  s2[x+i] == '2')
            return false;
    return true;
}
int main () {
    freopen("xx.in","r",stdin);
    while (cin>>s1>>s2) {
        l1=s1.length();
        l2=s2.length();
        int i,ans;
        for ( i = 0; i < l1; i++)
            if ( check1(i) )
                break;
        int j;
        for ( j = 0; j < l2; j++)
            if ( check2(j) )
                break;
        ans=min ( max (l1,l2+i),max(l2,l1+j));
        cout<<ans<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值