近期简单题目归纳
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;
}
}