第三章答案

地址:http://www.th7.cn/Program/java/201408/253926.shtml

3 习题

3.1 UVa1585--Score

#include int main() {    int T;    scanf("%d", &T);    while (T--) {        char s[100];        scanf("%s", s);        int sum = 0, cnt = 0;        for (int i = 0; s[i]; i++) {            if (s[i]==‘X‘) {                sum += cnt*(cnt+1)/2;                cnt = 0;            }            else cnt++;        }        printf("%d/n", sum+cnt*(cnt+1)/2);    }    return 0;}

每遇到X做一次更新,否则cnt++,注意第19行最后还要一次更新。

看了这段代码:http://blog.csdn.net/sinat_17231979/article/details/36869231后,发现还是想复杂了,没必要用前n项和公式,直接用一个变量记录当前有多少个O就行了:

#include int main() {    int T;    scanf("%d", &T);    while (T--) {        char s[100];        scanf("%s", s);        int sum = 0, cnt = 0;        for (int i = 0; s[i]; i++) {            if (s[i]==‘X‘) cnt = 0;            else {                cnt++;                sum += cnt;            }        }        printf("%d/n", sum);    }    return 0;}

3.2 UVa1586--Molar Mass

暴力每一位i,如果i+1位是数字,判断i+2位是不是数字,分情况计算数量;如果i+1位不是数字,那么数量就是默认的1。接着判断第i位是不是字母,不是则continue,否则累加相应的质量。

#include #include int main() {    int T;    scanf("%d", &T);    while (T--) {        char s[100];        scanf("%s", s);        double sum = 0, w;        for (int i = 0; s[i]; i++) {            // 算出后两位所代表的数值            if (isdigit(s[i+1])) {                if (isdigit(s[i+2])) w = 10*(s[i+1]-‘0‘)+s[i+2]-‘0‘;                else w = s[i+1] - ‘0‘;            }            else w = 1;            // 判断第一位            if (!isalpha(s[i])) continue;            else if (s[i] == ‘C‘) sum += 12.01*w;            else if (s[i] == ‘H‘) sum += 1.008*w;            else if (s[i] == ‘O‘) sum += 16.00*w;            else sum += 14.01*w;        }        printf("%.3lf/n", sum);    }    return 0;}

3.3 UVa1225--Digit Counting

#include int main() {    int T;    scanf("%d", &T);    while (T--) {        int N, i, t, a[10] = {};        scanf("%d", &N);        for (i = 1; i <= N; i++) {            t = i;            while (t) a[t%10]++, t/=10;        }        for (i = 0; i < 9; i++) printf("%d ", a[i]);        printf("%d/n", a[9]);    }    return 0;}

直接每组暴力都能过。如果会TLE,也可以建立二维数组a[10000][10],先暴力一轮求出数据。后面只要打表就行了。

3.4 UVa455--Periodic Strings

算一个字符串的周期,其周期一定是长度的约数,按这一点枚举,并写一个判断T是不是一个字符串的周期的函数(isThePeriod)即可。

输入格式略坑,每两组测试间会有一个空行,所以我用第19行那样的方式解决。

最后注意输出格式,也要每两个隔一个空行~~~

#include #include int isTthePeriod(char s[], int T) {    for (int i = 0; i < T; i++) {        for (int j = i+T; j < strlen(s); j+=T)            if (s[i] != s[j]) return 0;    }    return 1;}int main() {    int T, kase, len, i;    scanf("%d", &T);    for (kase = 1; kase <= T; kase++)    {        char s[100];        while (scanf("%s", s), len = strlen(s), !len);        for (i = 1; i <= len; i++)            if (len%i == 0 && isTthePeriod(s,i)) break;        if (kase != 1) putchar(‘/n‘);        printf("%d/n", i);    }    return 0;}

3.5 UVa227--Puzzle

这题稍微有些麻烦了,模拟操作,我尽量进行了些优化,而且为了方便交换变量,用了C++里algorithm的swap,没有自己写交换函数。【基本框架】将5*5网格定义为全局变量s(从1开始编号),当前空格所在行列为x,youtput函数用来输出s的矩阵形式ok用来操作一个命令为ch的移动,返回值1代表操作成功,返回0代表失败。成功的话,要更新相应的x、y和进行交换操作swaptest用来完成每组测试的操作 总结:对于复杂的问题,要想清思路,然后把大问题划分成一个个小的子问题去求解。

#include #include using namespace std;int x, y;char s[6][6];void output() {    for (int i = 1; i <= 5; i++) {        for (int j = 1; j < 5; j++)            printf("%c ", s[i][j]);        printf("%c/n", s[i][5]);    }}int ok(char ch) {    switch (ch) {    case ‘A‘:        if (x == 1) return 0; else x--;        swap(s[x][y], s[x+1][y]); break;    case ‘B‘:        if (x == 5) return 0; else x++;        swap(s[x][y], s[x-1][y]); break;    case ‘L‘:        if (y == 1) return 0; else y--;        swap(s[x][y], s[x][y+1]); break;    case ‘R‘:        if (y == 5) return 0; else y++;        swap(s[x][y], s[x][y-1]); break;    }}int test() {    char ch;    int i, j;    for (i = 1; i <= 5; i++) for (j = 1; j <= 5; j++)        if (s[i][j] == ‘ ‘) x = i, y = j;    while ((ch = getchar()) != ‘0‘) {        if (ch == ‘/n‘) continue;        if (!ok(ch)) {  // 非法操作,仍要清掉字符‘0‘前的值            while (getchar() != ‘0‘);            return 0;        }    }    return 1;}int main() {    int kase, i, j;    for (kase = 1; ; kase++) {        gets(&s[1][1]);        if (s[1][1] == 0) {kase--; continue;}   // 注意此处读到空串,要忽略读入continue        if (s[1][1] == ‘Z‘ && s[1][2] == 0) break;        if (kase != 1) putchar(‘/n‘);        printf("Puzzle #%d:/n", kase);        for (i = 2; i <= 5; i++) gets(&s[i][1]);        if (test()) output();        else printf("This puzzle has no final configuration./n");    }    return 0;}

3.6 UVa232--Crossword Answers

这题就是像中学英语填单词的那种网格。需要对起始点编号,然后按行输出、再按列输出所有单词。

#include #include int main() {    int n, m, a[15][15], k, i, j;    char s[15][15];    for (int kase = 1; ; kase++) {        if (scanf("%d%d ", &n, &m) != 2) break;        k = 0;        memset(a, 0, sizeof(a));        memset(s, 0, sizeof(s));        for (i = 1; i <= n; i++) gets(&s[i][1]);        for (i = 1; i <= n; i++) for (j = 1; j <= m; j++) {            if (s[i][j] == ‘*‘) s[i][j] = 0;            if (!(s[i-1][j]&&s[i][j-1]) && s[i][j]) a[i][j] = ++k;        }        if (kase != 1) putchar(‘/n‘);        printf("puzzle #%d:/nAcross/n", kase);        for (i = 1; i <= n; i++) for (j = 1; j <= m; j++)            if (s[i][j] && !s[i][j-1]) printf("%3d.%s/n", a[i][j], s[i]+j);        printf("Down/n");        for (i = 1; i <= n; i++) for (j = 1; j <= m; j++) {            if (s[i][j] && !s[i-1][j]) {                printf("%3d.", a[i][j]);                for (k = i; s[k][j]; k++) putchar(s[k][j]);                putchar(‘/n‘);            }        }    }    return 0;}

3.7 UVa1368--DNA Consensus

思路:找出每列中ACGT出现次数最多的字符,就是最优解序列在这一列的字符值。

#include #include inline int c2d(char c) {    if (c == ‘A‘) return 0;    else if (c == ‘C‘) return 1;    else if (c == ‘G‘) return 2;    else return 3;}inline int d2c(int d) {    if (d == 0) return ‘A‘;    else if (d == 1) return ‘C‘;    else if (d == 2) return ‘G‘;    else return ‘T‘;}int main() {    int T, m, n, i, j, a[1010][4], sum;    char s[50][1010];    scanf("%d", &T);    while (scanf("%d%d ", &m, &n) == 2) {        for (i = 0; i < m; i++) gets(s[i]);        memset(a, 0, sizeof(a));        for (i = 0; i < m; i++) for (j = 0; j < n; j++)            a[j][ c2d(s[i][j]) ]++;        for (sum = j = 0; j < n; j++) {            int the_max = a[j][0], id = 0;            for (i = 1; i < 4; i++) if (a[j][i]>the_max)                id = i, the_max = a[j][i];            putchar(d2c(id));            sum += m - the_max;        }        printf("/n%d/n", sum);    }    return 0;}

3.8 UVa202--Repeating Decimals

这题需要模拟除法,当出现相同的余数时,就代表循环点的出现。下面我以5/7为例详细的讲下思路。
如上图,第0步,分子是5,分母是7(分母在整个除法中始终不变),5/7的商是0,代表这个除法的整数部分是0,,余数是5,乘以10,得50作为第1步的分子;50/7的商为7,代表这个除法的第一位小数是7,余数是1,乘以10,得10作为第2步的分子...可以发现每步的除法只跟分子有关,也就是当分子出现重复值,如上图第1步和第7步的分子值都为50时,第7步后面的运算其实是在重复第1步至第6步间的运算。所以第1步至第7步就是一个循环节。 程序实现中,可以不用存储余数的值,只需存储上图中的分子和商,我定义了A[2][3010],用A[0][j]存储第j步的分子,A[1][j]存储第j步的商。注意最后的数值由商可以直接构成,如上图的红色字体,数值为0.7142857142...

#include int A[2][3010], p, q;// 找i位之前是否有重复分子出现;有则返回周期,否则返回-1.inline int myfind() {    for (p = 1; p < q; p++) {        if (A[0][p] == A[0][q])            return q - p;    }    return -1;}int main() {    int kase, a, b, i, len;    for (kase = 1; scanf("%d%d", &a, &b) != EOF; kase++) {        A[0][0] = a; A[1][0] = a/b;        for (q = 1; ; q++) {            A[0][q] = (A[0][q-1] - b*A[1][q-1])*10;            A[1][q] = A[0][q]/b;            len = myfind();            if (len > 0) break;        }        printf("%d/%d = %d.", a, b, A[1][0]);        for (i = 1; i < p; i++) printf("%d", A[1][i]);        putchar(‘(‘);        for (i = p; i < q; i++) {            if (i > 50) {                printf("...");                break;            }            printf("%d", A[1][i]);        }        printf(")/n   %d = number of digits in repeating cycle/n/n", len);    }}

3.9 UVa10340--All in All

遍历后者,找前者往后是否有对应的字符。

#include #include using namespace std;int fun(string& a, string& b) {    int i, j = 0;    for (i = 0; i < a.size(); i++, j++) {        while (j < b.size() && a[i]!=b[j]) j++;        if (j == b.size()) return 0;    }    return 1;}int main() {    string a, b;    while (cin >> a >> b) {        if (fun(a,b)) cout << "Yes/n";        else cout << "No/n";    }}

3.10 UVa1587--Box

只要用一堆疯狂的条件分支就能解答此题了:http://blog.csdn.net/u013451221/article/details/37672039。不过这里我更乐意把数据“标准化”,然后用C++构造“Face类”来求解。 首先构造一个宽w一定不小于高h的“面类(Face)”,并且按h为第一级,w为第二级准则从小到大排序。如果是能组成长方体的,边长肯定只有三种值,不妨设从小到大依次为a,b,c。则输入的6个面排序后,一定满足以下分布:
vczltcSz5NKqzPW8/qGjCjxwcmUgY2xhc3M9"brush:java;">#include #include #includeusing namespace std;struct Face{ int h, w; void make(int x, int y) { h = min(x,y); w = max(x,y); } bool operator < (const Face& b) const { if (h == b.h) return w < b.w; else return h < b.h; } bool operator == (const Face& b) const { return (h == b.h) && (w == b.w); }};vector A(6);int test1() { for (int i = 0; i < 6; i += 2) if (!(A[i]==A[i+1])) return 0; return 1;}int test2() { if (A[0].h==A[2].h && A[0].w==A[4].h && A[2].w==A[4].w) return 1; else return 0;}int main() { int x, y; while (cin >> x >> y) { A[0].make(x, y); for (int i = 1; i < 6; i++) { cin >> x >> y; A[i].make(x, y); } sort(A.begin(), A.end()); if (test1() && test2()) cout << "POSSIBLE/n"; else cout << "IMPOSSIBLE/n"; } return 0;}

3.11 UVa1588--Kickdown

假设固定装置s1,那么装置s2只要初始状态左端与s1左端对齐(该状态用偏移量k=0来标记),然后测试k=0时,两个装置是不是”每一位的和都不会超过3“就行了,如果不行就k++,继续往右边偏移进行测试。可以知道肯定存在着一个k能使其成立的(也就是s2左端接在s1右端时)。用这种方式遍历,找到的第一个可行解就是最佳解。 不过上述讨论还遗漏了一种组合方式,就是s2也可以往左偏移。其实将上述解法写成一个fun函数进行封装,外界(main函数)只要巧妙的利用对称性,就能重复利用上一段的代码了。

#include #include #include using namespace std;int len1, len2;char s1[110], s2[110];int test(int k, char s1[], char s2[]) {    for (int i = 0; s1[k+i] && s2[i]; i++)        if (s1[k+i]+s2[i]-2*‘0‘ > 3) return 0;    return 1;}int fun(char s1[], char s2[]) {    int k = 0;    while (!test(k,s1,s2)) k++;    return max(strlen(s1), strlen(s2)+k);}int main() {    while (scanf("%s%s", s1, s2) != EOF) {        printf("%d/n", min(fun(s1,s2), fun(s2,s1)));    }    return 0;}

3.12 UVa11809--Floating-Point Numbers

首先要知道二进制小数的原理:
本题的思路就是先把所有的M、E对应的值算出来,记为矩阵C,其中C[M,E]=尾数M、阶码E对应的最大值。然后对于输入的AeB,找出C中与其相等的值所在的行M、列E即是答案。 不过这里有两个要点。一是这个数值太大,可以达到2^(2^30-1),远超了double的存储范围。所以我们不妨对数值做一个变换,取以10为底的对数值来存储。二是计算过程的舍尾误差与double本身存在的误差会导致精度问题。所以可以在矩阵C中找与输入值最接近的作为匹配点,也就是差值的绝对值最小。
最后还有M=0,E=1的特殊点,在程序中会出现0.0-0.0<0.0条件为否的错误,导致pi,pj无法更新,这个问题只要把pi、pi分别初始化为0、1就能解决了。

#include #include #include double C[10][31];void init() {    int i, j, v;    double f[10] = {0.5}, g[31], t;    for (i = 1, t = 0.5; i < 10; i++) {        f[i] = f[i-1] + t/2;        t /= 2;    }    for (i = 0; i < 10; i++) f[i] = log10(f[i]);    for (i = 1, v = 2; i <= 30; i++) {        g[i] = (v - 1.0)*log10(2.0);        v <<= 1;    }    for (i = 0; i < 10; i++) for (j = 1; j <= 30; j++)        C[i][j] = f[i] + g[j];}int main() {    int i, j;    char s[100], *p;    double A, B;    init();    while (scanf("%s", s), strcmp(s, "0e0")) {        p = strchr(s, ‘e‘);        *p = 0;                 // 将‘e‘所在位置变为‘/0‘        sscanf(s, "%lf", &A);        sscanf(p+1, "%lf", &B);        int pi = 0, pj = 1;        B = A = log10(A) + B;   // 接下来A存储表达式值,B记录差值        for (i = 0; i < 10; i++) for (j = 1; j <= 30; j++)        if (fabs(A-C[i][j]) < B) pi = i, pj = j, B = fabs(A-C[i][j]);        printf("%d %d/n", pi, pj);    }    return 0;}
时间: 2024-10-13 16:42:56

第三章答案的相关文章

算法竞赛入门经典(刘汝佳)课后习题前三章答案

本文转载: 第一章习题1-1#include <stdio.h>int main(){int a,b,c;double d;scanf("%d%d%d",&a,&b,&c);d=(double)(a+b+c);printf("%.3lf\n",d/3.0);return 0;} 习题1-2#include <stdio.h>int main(){int f;double c;scanf("%d",&

思科第一学期第三章答案

最近要准备cisco的学期考试,整理了一下考试答案. 1   哪个应用层协议通常用于支持客户端与服务器之间的文件传输? HTML HTTP FTP Telnet 2 应用层软件的两种形式是什么?(选择两项) 应用程序 对话 请求 服务 语法 3 网络管理员正在为拥有二十五名用户的新分公司设计网络.使用客户端-服务器模型有哪些优势?(选择两项) 集中管理 不需要专用软件 更易于执行安全管理 实施成本更低 提供单一故障点 4 资源记录在 DNS 中有何作用? 临时保存解析的条目 服务器用其解析域名

c++面向对象程序设计 谭浩强 第三章答案

2: #include <iostream> using namespace std; class Date {public: Date(int,int,int); Date(int,int); Date(int); Date(); void display(); private: int month; int day; int year; }; Date::Date(int m,int d,int y):month(m),day(d),year(y) { } Date::Date(int m

思科CCNA第四学期第三章答案

1 哪种说法是对数据链路连接标识符 (DLCI) 的最佳描述? 用于标识通过帧中继网络连接的目的路由器的本地地址 用于标识虚电路的具有本地意义的地址 用于标识路由器和帧中继交换机之间的接口的逻辑地址 用于标识 DCE 的逻辑地址 2 请参见图示.从该输出可以得到什么结论? Serial 0/0/0 配置了 DLCI 201. Serial 0/0/0 已启用帧中继逆向 arp 功能. Serial 0/0/0 配置的 IP 地址为 172.16.4.3. Serial 0/0/0 已使用 fra

数据库课本SQL第三章答案

3 .用 sQL 语句建立第二章习题 5 中的 4 个表. 答: 对于 S 表: S ( SNO , SNAME , STATUS , CITY ) ; 建 S 表: CREATE TABLE S ( Sno C(2) UNIQUE,Sname C(6) ,Status  C(2),City C(4)); 对于 P 表: P ( PNO , PNAME , COLOR , WEIGHT ); 建 P 表 : CREATE TABLE P(Pno  C(2)  UNIQUE,Pname  C(6)

思科CCNA第三学期第三章答案

1.如果邻居交换机端口处于"动态期望"模式,那么哪些交换机端口模式可以让交换机成功形成中继链路? 动态期望模式 打开或动态期望模式 打开.自动或动态期望模式 打开.自动.动态期望或非协商模式 2.当删除 VLAN 时,该 VLAN 的成员端口会发生什么变化? 这些端口将无法与其它端口通信. 这些端口会默认返回到管理 VLAN 中. 这些端口会自动成为 VLAN1 的成员. 这些端口仍然保持该 VLAN 的成员身份.直到交换机重新启动后,它们将成为管理 VLAN 的成员 3.网络管理员正

思科CCNA第二学期第三章答案

1.请参见图示.Router1 和 Router2 都运行 EIGRP.所有接口都正常运行,并且数据包能在所有网络之间转发.在 Router1 的路由表中可找到下列哪一项信息? Router1 有 6 个直连网络. 到达 172.16.0.0 网络的路由的管理距离为 90. 到达 172.16.0.0 的路由的度量为 1. 用于将数据包转发到 172.16.0.0 的接口始终为 S0/1 接口 2.下列关于度量的陈述,哪两项是正确的?(选择两项.) RIP 使用带宽作为度量. OSPF 使用延迟

明解C语言 中级篇 第三章答案

练习3-1 /* 猜拳游戏(其四:分割函数/显示成绩)*/ #include <time.h> #include <stdio.h> #include <stdlib.h> int human; /* 玩家的手势 */ int comp; /* 计算机的手势 */ int win_no; /* 胜利次数 */ int lose_no; /* 失败次数 */ int draw_no; /* 平局次数 */ char* hd[] = { "石头", &q

2014年软考-信息技术处理员-模拟试题及答案【第三章】

51CTO学院,在软考备考季特别整理了"2014年软考信息技术处理员模拟试题及答案[汇总篇]",帮助各位学院顺利过关!更多软件水平考试辅导及试题,请关注51CTO学院-软考分类吧! 查看汇总:2014年软考-信息技术处理员-模拟试题及答案[汇总篇]  ●备注视图中的注释信息在文稿演示时____(31)__B__. A.会显示 B.不会显示 C.显示一部分 D.显示标题 ●Access 2000关系数据库是____(32)_D___的集合. A.数据 B.数据库对象 C.表 D.关系 ●