2016.07.09完成 8 道题

本文精选了UVA在线评测平台上的多个经典编程题目解答,包括数字比较、字符串排序、三维点距离计算等,涵盖了算法设计、数据结构应用等多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVA-340

题解:求两个数。第一个是和提示串和原串相同的有多少个。另一个是原串中有的但是位置不同的有多少个。要注意如如果位置相同已经计算过了,那么不同的计数时原串的这个位置就不能计算来。其实只要用一个数组来统计每个数字被取用过几次,只要还有剩下,就可以取用,次数+1。


#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
int n,s[1010],g[1010],x,y,t[20],z[20];
int main (){
    scanf("%d",&n);
    int tot=0;
    while (n){
        tot++;
        cout<<"Game "<<tot<<":"<<endl;
        for (int i = 1; i <= 9; i++) t[i]=0;
        for (int i = 1; i <= n; i++){
            scanf("%d",&s[i]);
            t[s[i]]++;
        }
        while (true){
            x=0;y=0;
            for (int i = 1; i <= 9; i++) z[i]=0;
            for (int i = 1; i <= n; i++){
                scanf("%d",&g[i]);
                if (s[i] == g[i]) {
                    x++;
                    z[g[i]]++;
                }
            }
            for (int i = 1; i <= n; i++)
             if (s[i]!=g[i]){
                if (z[g[i]]+1 <= t[g[i]]) {
                    y++;
                    z[g[i]]++;
                }
            }
            if (g[1]==0)break;
            cout<<"    ("<<x<<","<<y<<")"<<endl;
        }
        scanf("%d",&n);
    }
} 

UVA-10420

题意:给你美女的国家和她的名字,要你统计每个国家有几个美女。按字典序输出国家和个数。
解体思路:写一个struct包含国家和姓名。以国家为关键字进行排序。循环扫一遍统计个数并输出。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
struct node {
    string country;
    string name;
} s[3000];
int n;
bool cmp(const node a,const node b){
    return a.country < b.country;
}
int main () {
    freopen("xx.in","r",stdin);
    scanf("%d",&n);
    for (int i = 1; i <= n; i++){
        cin>>s[i].country;
        getline(cin,s[i].name);
    }
    sort(s+1,s+1+n,cmp);
    int sum=1;
    for (int i = 1; i <= n; i++)
        if (s[i].country != s[i+1].country){
            cout<<s[i].country<<' '<<sum<<endl;
            sum=1;
        } else sum++;
}

UVA-10474

题意:给N个数和M个询问。求每次询问的数在N个数排序后的可以在第几位找到。
解题思路:对N个数进行排序,然后傻瓜循环找位置。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int n,m,s[12000];
bool cmp(int a, int b){
    return a<b;
}
int main (){
    freopen("xx.in","r",stdin);
    int num=0;
    while ( true ){
        cin>>n>>m;
        if (n == 0  &&  m == 0) break;
        cout<<"CASE# "<<++num<<":"<<endl;
        for (int i = 1; i <= n; i++)
            scanf("%d",&s[i]);
        sort(s+1,s+1+n,cmp);
        for (int k = 1; k <= m; k++){
            int c,tag=-1;
            scanf("%d",&c);
            for (int i = 1; i <= n; i++)
                if (s[i] == c) {
                    tag=i;
                    break;
                }
            if (tag != -1)
                printf("%d found at %d\n",c,tag);
            else printf("%d not found\n",c);
        }
    }
}

UVA-152

题意:给定若干个三维点,以0 0 0结束。求每个点和它最近的那个点的距离。并统计距离在0~1,1~2……9~10(前闭后开)这些区间内的个数。
解题思路:暴力解决 。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int sum[12],x[5100],y[5100],z[5100];
int dis(int i, int j) {
    int d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
    return (int) sqrt(d);
}
int main () {
    freopen("xx.in","r",stdin);
    memset(sum,0,sizeof(sum));
    int n;
    for (n = 1; ; n++) {
        scanf("%d%d%d",&x[n],&y[n],&z[n]);
        if (x[n] == 0  &&  y[n] == 0  &&  z[n] == 0)
            break;
    }
    n--;
    for (int i = 1; i <= n; i++){
        int mindis=1000000;
        for (int j = 1; j <= n; j++)
            if ( i != j ){
                int d = dis(i,j);
                if ( d < mindis )
                    mindis = d;
            }
        if (mindis < 10)    
            sum[mindis] ++ ;
    }
    for (int i = 0; i <= 9; i++)
        printf("%4d",sum[i]);
    printf("\n");
}

UVA-299

题意:每次只能交换相邻两个的顺序,求最小交换次数使得序列从小到大。
解题思路:每次只能交换相邻两个,我们不难想到冒泡排序。其实这就是求用冒泡排序所要进行多少次交换。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int n,s[70],t;
int main () {
    freopen("xx.in","r",stdin);
    scanf("%d",&t);
    while ( t-- ){
        scanf("%d",&n);
        for (int i = 1; i <= n; i++)
            scanf("%d",&s[i]);
        int ans=0,z;
        for (int k = 1; k <= n; k++)
            for (int i = n; i >= 2; i--) 
                if (s[i] < s[i-1]) {
                    ans++;
                    z=s[i];
                    s[i]=s[i-1];
                    s[i-1]=z;
                }
        cout<<"Optimal train swapping takes "<<ans<<" swaps."<<endl;
    }
}

UVA-120

题意:给一个堆,每次用铲子能把插入位置上面的倒置。求如何操作能让整个堆从上到下的大小时从小到大。
解题思路:首先我们可以想到,如果想把某个位置上的数字弄到我们想要的地方,只需要把它先倒置到顶部,在从要它去的地方插入再倒置一次,就可以来。那么我们可以想一下我们肯定要从底部着手,从下往上一块一块解决。
那么我们就需要知道正确的顺序 ——通过另开一个数组进行排序可以知道顺序
我们每次要操作哪块? ——不在正确位置上编号最大的那块
移动到哪里?—— 正确位置上
其实写道这里我发现我代码上写了一段很多余的操作。。。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
bool cmp(int a, int b){
    return a<b;
}
int s[60],z[60],n;
int main(){
    freopen("xx.in","r",stdin);
    char c;
    while (scanf("%d%c",&s[1],&c)!=EOF) {
        n=1;z[1]=s[1];
        while (c != '\n'){
            n++;
            scanf("%d%c",&s[n],&c);
            z[n]=s[n];
        }
        for (int i = 1; i <= n; i++)
            printf("%d ",s[i]);
        printf("\n");
        sort(z+1,z+1+n,cmp);
        int tag=1;
        s[0]=-1;z[0]=-2;
        while ( tag ){
            tag=0;
            for (int i = 1; i <= n; i++)
                if (s[i] != z[i] && s[tag] < s[i]) tag=i;
            if (tag && tag != 1) printf("%d ",n-tag+1);
            for (int i = 1; i <= tag/2 ;i++){
                int k=s[i];
                s[i]=s[tag-i+1];
                s[tag-i+1]=k;
            }
            tag=n;
            while (s[tag] == z[tag]) tag--;
            if (tag) printf("%d ",n-tag+1);
            for (int i = 1; i <= tag/2 ;i++){
                int k=s[i];
                s[i]=s[tag-i+1];
                s[tag-i+1]=k;
            }
        }
        printf("0\n");
    }
}

UVA-156

题意:给定若干个单词,#表示输入结束。求在无视大小写的情况下,无论经过如何排序都不会和其他单词相同的那些单词。按字典序从小到大输出。
解题思路:写个struct包含s1和s2,s2是对s1进行全部转换成小写并按字典序从小到大排序的字符串。以s2作为关键字进行排序。在排序完的序列中只要但前位置的s2与它前后的s2不相同,这个便是一个满足条件的单词。用另一个字符串数字存下。再按字典序排序,输出。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
struct node {
    string s1,s2;
} s[2000];
string ans[2000];
int n=0,la=0;
bool cmp1(const node a,const node b){
    return a.s2 < b.s2;
}
bool cmp2(const string a,const string b){
    return a<b;
}
int main () {
    freopen("xx.in","r",stdin);
    while (true ) {
        n++;
        cin>>s[n].s1;
        if (s[n].s1 == "#") break;
        s[n].s2 = s[n].s1;
        for (int i = 0; i < s[n].s1.length(); i++)
            if ( s[n].s2[i] >= 'A' && s[n].s2[i] <= 'Z')
                s[n].s2[i]= s[n].s2[i]-'A'+'a';
        for (int i = 0; i < s[n].s2.length(); i++)
            for (int j = i+1; j < s[n].s2.length(); j++)
                if (s[n].s2[i] > s[n].s2[j]) {
                    char c=s[n].s2[i];
                    s[n].s2[i] = s[n].s2[j];
                    s[n].s2[j]=c;
                }
    }
    n--;
    sort(s+1,s+1+n,cmp1);
    for (int i = 1; i <= n; i++)
        if (s[i].s2 != s[i+1].s2  &&  s[i].s2 != s[i-1].s2){
            la++;
            ans[la]=s[i].s1;
        }
    sort(ans+1,ans+1+la,cmp2);
    for (int i = 1; i <= la; i++)
         cout<<ans[i]<<endl;
}

UVA-400

题意:给定n和n个字符串,对n个字符串按字典序从小到大排序,按列优先顺序并以左对齐的方式输出,每个单词场宽为最长串长度+2,并且每行不超过60字符长度。
解题思路:这题是个大坑。
先进行排序,简单。
要计算能排几行几列。
列数 = (n-maxlength) / (maxlength+2)+1;
行数 = (n-1)/列数 +1;
然后就是愉快的输出控制了。坑。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
string s[300];
int n,maxlen,an,am;
bool cmp(const string a,const string b){
    return a<b;
}
int main (){
    freopen("xx.in","r",stdin);
    while (scanf("%d\n",&n) != EOF) {
        maxlen=0;
        for (int i = 1; i <= n; i++){
            getline(cin,s[i]);
            if (s[i].length() > maxlen)
                maxlen = s[i].length();
        }
        sort(s+1,s+1+n,cmp);
        //  (maxlen+2)*am + maxlen  = 60 
        am = (60-maxlen) / (maxlen +2) +1;
        an = (n-1) / am +1;
        for (int i = 1; i <= 60; i++)
            printf("-");
        printf("\n");
        maxlen+=2;
        for (int i = 1; i <= an; i++){
            for (int j = i; j <= n; j+= an){
                cout<<s[j];
                for (int k = 1; k <= maxlen - s[j].length(); k++)
                    printf(" ");
            }
            printf("\n");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值