帝国国王科技大学上机题解
来源:互联网 发布:世界第一社交网络 编辑:程序博客网 时间:2024/05/02 05:05
1.变位词问题(18分)
问题描述
所谓变位词,是指组成各个单词的字母完全相同,只是字母排列的顺序不同。例如:silent和listen就是一对变位词。给出两个字符串,要求判断其是否互为变位词,若是,返
回“Yes”,否则返回“No”。
Input
输入正整数N,表示N例测试。接着输入N组数据,每组数据一行,包含两个字符串。
Output
对每组输入数据,输出一行,“Yes”表示是变位词,“No”表示不是变位词。
Sample Input
2
silent listen
stop sort
Sample Output
Yes
No
解题思路:
利用map把两个字符串里的每个字符的个数统计到数组a和数组b中。如果完全相同,返回Yes,不同的话返回No。
PS:可能两个字符串中会包含!@#$%^&等字符。
代码:
#include<iostream>#include<cstdio>#include<vector>#include<algorithm>#include<cstring>#include<map>#define maxn 1005using namespace std;int a[1005];int b[1005];char str1[10005];char str2[10005];map <char,int> mq;int main(){ int n,i,len; while(cin>>n) { while(n--) { int t=0; mq.clear(); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); cin>>str1; len=strlen(str1); for(i=0; i<len; i++) { if(!mq[str1[i]]) { mq[str1[i]]=++t; a[t]++; } else { a[mq[str1[i]]]++; } } cin>>str2; len=strlen(str2); for(i=0; i<len; i++) { if(!mq[str2[i]]) { mq[str2[i]]=++t; b[t]++; } else { b[mq[str2[i]]]++; } } /*if(strcmp(str1,str2)==0) { cout<<"No"<<endl; continue; }*/ int flag=1; for(i=0; i<1000; i++) { if(a[i]!=b[i]) { flag=0; break; } } if(flag) cout<<"Yes"<<endl; else cout<<"No"<<endl; } } return 0;}/*4beijinguniversityofpostsandtelecommunicationsnnsemnoimfeiaugtyittouinjpdonssaiebcsiervctolschoolofcomputerscience icooeeorhufmpcntepcslcscdmpnb.enuet.@ua name@bupt.edu.cncongratulations nncatrlsaoogucit*/
2.加密问题(16分)
问题描述
信息社会,密码与我们生活息息相关。为了安全起见,可通过简单加密机制把明文加密成密文。这里的加密机制是利用手机上的字母与数字键的对应关系:1--1,abc--2,def--3,ghi--4,jkl--5,mno--6,pqrs--7,tuv--8,wxyz--9,0--0。加密机制为:
1)密码中出现的小写字母都变成对应的数字;
2)密码中出现的大写字母都变成小写之后往后移一位,如果是大写字母Z,则后移一位变成a;
3)数字和其他的符号都不做变换。
声明:密码中没有空格,可包含特殊字符,如~!@#$等。
Input
输入正整数N,表示N例测试。接着输入N组数据,每组数据一行,包含一个明文字符串,长度不超过100。
Output
对每组输入数据,输出一行对应的密文。
Sample Input
2
ZHANGsan&2016
Name@32#
Sample Output
Aiboh726&2016
O263@32#
代码:
PS:代码写的比较乱,用了很多if,else。。。
#include<iostream>#include<cstdio>#include<vector>#include<algorithm>#include<cstring>#define maxn 1005using namespace std;char str1[1005];int main(){ int n,i,len; while(cin>>n) { while(n--) { cin>>str1; len=strlen(str1); for(i=0; i<len; i++) { if(str1[i]>='A'&&str1[i]<='Y') { str1[i]=str1[i]-'A'+'a'+1; } else if(str1[i]=='Z') { str1[i]='a'; } else if(str1[i]>='a'&&str1[i]<='c') { str1[i]='2'; } else if(str1[i]>='d'&&str1[i]<='f') { str1[i]='3'; } else if(str1[i]>='g'&&str1[i]<='i') { str1[i]='4'; } else if(str1[i]>='j'&&str1[i]<='l') { str1[i]='5'; } else if(str1[i]>='m'&&str1[i]<='o') { str1[i]='6'; } else if(str1[i]>='p'&&str1[i]<='s') { str1[i]='7'; } else if(str1[i]>='t'&&str1[i]<='v') { str1[i]='8'; } else if(str1[i]>='w'&&str1[i]<='z') { str1[i]='9'; } } cout<<str1<<endl; } } return 0;}/*2School!Of@Computer#Science$NLP2016^BYR*bupt%BeiJing/China*/
3.求连续子数组最大和(20分)
问题描述
输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值,并给出子数组的首末位置。
Input
输入正整数N,表示N例测试。接着输入N组数据,每组数据一行,包含一个数组。
Output
对每组输入数据,输出该数组对应的最大连续子数组和,子数组的首位置,末位置。
Sample Input
2
1 -2 3 10 -4 7 2 -5
1 -9 5 5
Sample Output
18 2 6
10 2 3
解题思路:
如果用a表示给定的初始数组,dp[i]表示以i为末位置的最大连续子数组的和,那么dp[i]=max(dp[i-1]+a[i],dp[i])
代码:
#include<iostream>#include<cstdio>#include<vector>#include<algorithm>#include<cstring>#define maxn 1005using namespace std;int a[1005];int dp[1005];char str[1005];int ma(int a,int b){ if(a>b) return a; return b;}int main(){ int n,i,len,m; while(cin>>n) { gets(str); while(n--) { memset(dp,0,sizeof(dp)); m=0; gets(str); len=strlen(str); int tmp=0,flag=0; for(i=0; i<len; i++) //将字符串处理成int数组保存在数组a中 { if(str[i]=='-') { flag=1; } else if(str[i]==' ') { if(flag) a[m++]=0-tmp; else a[m++]=tmp; flag=0; tmp=0; } else tmp=tmp*10+(str[i]-'0'); } if(flag) a[m++]=0-tmp; else a[m++]=tmp; flag=0; tmp=0; /* cout<<m<<endl; for(i=0;i<m;i++) cout<<a[i]<<" "; cout<<endl; */ if(a[0]>=0) dp[0]=a[0]; else dp[0]=0; for(i=1; i<m; i++) //利用递推公式 dp[i]=ma(a[i],dp[i-1]+a[i]); int fla=0; //处理没有正数的情况 ,特判 for(i=0; i<m; i++) { if(a[i]>0) { fla=1; } } if(fla==0) //处理没有正数的情况 ,特判 { int ss,ee,mm=-1000000000; for(i=0; i<m; i++) { if(a[i]>mm) { mm=i; ss=i; ee=i; } } cout<<mm<<" "<<ss<<" "<<ee<<endl; continue; } int mm=-1000000000,e,s; for(i=0; i<m; i++) //找到dp的最大值 { if(dp[i]>mm) { mm=dp[i]; e=i; } } int pp=mm; for(i=e; i>=0; i--) //根据总和和末位置找到起始位置 { pp-=a[i]; if(pp==0) { s=i; break; } } cout<<mm<<" "<<s<<" "<<e<<endl; } } return 0;}/*1001 -2 3 10 -4 7 2 -51 -9 5 5-1 -1 -1-1 2 20 -1 -131 -2 3 10 -4 7 2 -5 -19 10 8 -3 -8 361 59 62 -107 22 23 -113 14 54 57 -76 -116 78 0 7 -70 50 -58 -94 1 53 38 55 65 16 48 32 8 27 8 -108 63 -50 14 69 -103 -112 -51 40 5396 30 163 37 65 -232 121 -295 15 119 11 177 -149 128 68 -217 -290 196 169 -32 -261 194 -85 48 -87 84 89 -152 -98 96 177 198 -144 154 -67 125 -224 -110 182 -155 72 43 92 -127 40 84 85 -285 171 69 157 176 -24 149 -98 59 188 58 193 145 -208 32 -9 182 -191 97 54 92 101 -79 -111 35 -28 -48 96 128 46 -193 -182 -111 45 170 182 136 147 79 12 53 11 -171 90 199 26 120 60 59 52 -111 -113 148*/
4.整数的最小平方分解(23分)
问题描述
给定一个正整数n,总能分解成若干个完全平方数的和(这里完全平方数为1,4,9,16,25,...),请找出n的最小平方分解数,例如,n=12时,12=4+4+4,返回最小平方分解数3;n=13时,13=4+9,返回最小平方分解数2。
Input
输入正整数N,表示N例测试。接着输入N组数据,每组数据一行,包含一个正整数。
Output
对每组输入数据,输出其最小平方分解数。
Sample Input
4
12
13
2016
Sample Output
2
3
2
3
解题思路:
思路一,可以利用递归的思想dfs(cur,deep),寻找最优解。cur是当前的值,deep是当已经用的平方数的个数。 如果cur为0,那么把deep和结果比较,选小的。为了记忆化搜索,用vis数组保存cur的是否访问过,还有p数组,p[i]到达cur状态所用的最小步数。
1)如果cur没访问过,便访问。
2)如果cur访问过,并且当前到达的步数更少的话,也可以继续搜索。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define INF 0x7fffffff#define maxn 1000005using namespace std;int ans;int a[maxn];int m,n;int vis[maxn];int p[maxn];void dfs(int cur,int deep){ if(deep>10) return; if(cur==0) { if(deep<ans) { ans=deep; return; } } else if(cur<0) { return; } for(int i=sqrt(cur); i>=1; i--) { int t=cur/(i*i); for(int j=1; j<=t; j++) { if(!vis[cur-j*i*i]) { vis[cur-j*i*i]=1; p[cur-j*i*i]=deep+j; dfs(cur-j*i*i,deep+j); } if(vis[cur-j*i*i]&&p[cur-j*i*i]>deep+j) { vis[cur-j*i*i]=1; p[cur-j*i*i]=deep+j; dfs(cur-j*i*i,deep+j); } } }}int main(){ while(cin>>n) { while(n--) { memset(vis,0,sizeof(vis)); memset(p,0,sizeof(p)); cin>>m; ans=INF; dfs(m,0); cout<<ans<<endl; } } return 0;}
思路二,这个题是典型的完全背包。
具体可以参加背包九讲问题。
当然这个题有些许不同,动态转移方程为dp[j]=min(dp[j-i*i]+1,dp[j]);
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#define INF 0x7fffffff#define maxn 400005using namespace std;int dp[maxn];void pre(){ int i,j; for(i=1;i<maxn;i++) dp[i]=INF; dp[0]=0; for(i=1;i<=1000;i++) { for(j=0;j<maxn;j++) { if(j>=i*i&&dp[j-i*i]!=INF) { dp[j]=min(dp[j-i*i]+1,dp[j]); } } }}int main(){ pre(); int n,m; while(cin>>n) { while(n--) { cin>>m; cout<<dp[m]<<endl; } } return 0;}
5.矩阵的ZigZag排列(23分)
问题描述
输入一个仅包含正整数n×n矩阵array,输出该矩阵的ZigZag排列,其中array[0][0]是排列的起点,array[n-1][n-1]是排列的终点。例如:输入一个4×4的矩阵
输出其ZigZag排列:1 2 5 9 6 3 4 7 10 13 14 11 8 12 15 16
Input
输入正整数N,表示N例测试。接着输入N组数据,每组数据为一个n×n的矩阵,即先输入n,然后输入n行数据。
Output
对每组输入数据,输出一行该矩阵的ZigZag排列。
Sample Input
2
2
1 2
3 4
4
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Sample Output
1 2 3 4
1 2 5 9 6 3 7 10 13 14 11 8 12 15 16
解题思路:
其实这个题目只有四个方向,正右,左下,正下,右上。如果x,y表示当前坐标。这四个方向坐标变化依次为+{{0,1},{1,-1},{1,0},{-1,1}};
可以采用递归的思想,关键就是判断方向,什么时候改变方向,有几种可能。
代码:
#include<iostream>#include<cstdio>#define maxn 1005using namespace std;int a[maxn][maxn];int d[4][2]= {{0,1},{1,-1},{1,0},{-1,1}};int m;void dfs(int curx,int cury,int dir){ cout<<a[curx][cury]<<" "; if(curx==m&&cury==m) return; curx=curx+d[dir][0]; cury=cury+d[dir][1]; if(dir==0) { if(curx==1) dir=1; else dir=3; } else if(dir==1) { if(curx==m) dir=0; else if(cury==1) dir=2; else dir=1; } else if(dir==2) { if(cury==1) dir=3; else dir=1; } else { if(curx==1) dir=0; else if(cury==m) dir=2; else dir=3; } dfs(curx,cury,dir);}int main(){ int n,i,j; while(cin>>n) { while(n--) { cin>>m; for(i=1; i<=m; i++) { for(j=1; j<=m; j++) { cin>>a[i][j]; } } //cout<<"****"<<endl; dfs(1,1,0); cout<<endl; } } return 0;}/*2826 -57 30 16 0 45 -16 -32-47 -53 18 0 38 -28 12 212 -49 9 41 53 -59 -7 -1451 21 1 27 38 -29 29 3760 26 36 -44 14 -12 -58 571 -2 23 32 30 -16 62 10-44 17 34 23 14 -36 46 3626 -3 0 40 7 -5 49 5116-226 247 6 -116 227 32 234 -42 -125 -36 153 71 -144 110 -66 -217-3 80 -65 6 -137 130 27 -124 244 -241 -28 197 -170 97 2 3045 -150 69 110 100 165 54 217 72 196 207 219 -72 159 93 107225 159 252 62 50 99 13 -92 236 14 -125 229 127 202 11 176219 -148 -7 163 90 -157 -98 83 -172 119 208 -183 151 149 230 207-17 79 -12 168 165 -108 130 -230 136 79 232 -200 191 180 111 3684 30 -5 252 -132 13 221 58 74 124 180 -90 76 150 -23 -23725 -147 120 108 -220 52 77 148 -216 14 45 35 110 173 188 185123 -50 112 167 52 -131 -29 10 -221 72 -220 -207 -73 9 -22 177-249 75 83 -79 202 27 -146 -3 195 126 163 210 75 159 31 -250-87 -43 105 -107 142 -219 207 -196 230 -225 -80 -79 -198 32 216 10159 63 155 -14 -33 -194 -88 156 86 104 146 163 157 14 108 -43184 231 166 224 81 126 205 159 241 -181 -224 -6 248 -1 170 115120 76 98 -58 -243 152 107 86 62 -215 43 165 27 -105 -81 16534 -248 125 115 2 226 21 -43 163 168 99 211 -1 -246 215 204-208 199 19 -120 15 146 -29 -13 166 89 148 -250 -66 104 40 -253*/
- 帝国国王科技大学上机题解
- 帝国国王科技大学上机题解(二)
- 国王游戏 题解
- NOIP2012 国王游戏 题解
- [noip2012]国王游戏 题解
- 2017年华中科技大学上机详解
- NOIP2012提高组day1T2国王游戏 题解
- 题解与上机指导
- 西南科技大学 信息工程学院 院赛 部分题题解,持续更新.
- [题解] NOIP2012 国王游戏(数论+高精)
- 南理工复试上机题解
- 算法第二次上机部分题解
- 西南科技大学第九届程序设计竞赛B题解题报告(线段树版)
- 《C++程序设计题解与上机指导》
- 清华大学07年复试上机题题解
- 华为三道上机题解答
- 计算机复试上机题解题报告
- C程序设计题解与上机指导
- 【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)
- linux awk命令详解
- shiro url和过滤器处理功能
- 理解smart pointer之一(auto_ptr介绍)
- 【Training Contest】2016.03.08
- 帝国国王科技大学上机题解
- 第二周项目二———就拿胖子说事
- Java简单url识别
- 直流高压脉冲发生电路分析
- 我的第一篇博客奉献给了CSDN
- android 6.0(api 23) SDK,不再提供org.apache.http.*解决方法。
- 随机梯度下降(Stochastic gradient descent)和 批量梯度下降(Batch gradient descent )
- ANDROID 一键搞定JNI创建C头文件
- std::auto_ptr 官网例子