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");
}
}
}