首页 > 代码库 > 基础搜索算法题解(N-R)
基础搜索算法题解(N-R)
练习链接:http://acm.njupt.edu.cn/vjudge/contest/view.action?cid=171#overview
N题 Shredding Company
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 4398 | Accepted: 2520 |
Description
2.It shreds (or cuts) the sheet into pieces each of which has one or more digits on it.
3.The sum of the numbers written on each piece is the closest possible number to the target number, without going over it.
For example, suppose that the target number is 50, and the sheet of paper has the number 12346. The shredder would cut the sheet into four pieces, where one piece has 1, another has 2, the third has 34, and the fourth has 6. This is because their sum 43 (= 1 + 2 + 34 + 6) is closest to the target number 50 of all possible combinations without going over 50. For example, a combination where the pieces are 1, 23, 4, and 6 is not valid, because the sum of this combination 34 (= 1 + 23 + 4 + 6) is less than the above combination‘s 43. The combination of 12, 34, and 6 is not valid either, because the sum 52 (= 12 + 34 + 6) is greater than the target number of 50.
Figure 1. Shredding a sheet of paper having the number 12346 when the target number is 50
There are also three special rules :
1.If the target number is the same as the number on the sheet of paper, then the paper is not cut.
For example, if the target number is 100 and the number on the sheet of paper is also 100, then
the paper is not cut.
2.If it is not possible to make any combination whose sum is less than or equal to the target number, then error is printed on a display. For example, if the target number is 1 and the number on the sheet of paper is 123, it is not possible to make any valid combination, as the combination with the smallest possible sum is 1, 2, 3. The sum for this combination is 6, which is greater than the target number, and thus error is printed.
3.If there is more than one possible combination where the sum is closest to the target number without going over it, then rejected is printed on a display. For example, if the target number is 15, and the number on the sheet of paper is 111, then there are two possible combinations with the highest possible sum of 12: (a) 1 and 11 and (b) 11 and 1; thus rejected is printed. In order to develop such a shredder, you have decided to first make a simple program that would simulate the above characteristics and rules. Given two numbers, where the first is the target number and the second is the number on the sheet of paper to be shredded, you need to figure out how the shredder should "cut up" the second number.
Input
tl num1
t2 num2
...
tn numn
0 0
Each test case consists of the following two positive integers, which are separated by one space : (1) the first integer (ti above) is the target number, (2) the second integer (numi above) is the number that is on the paper to be shredded.
Neither integers may have a 0 as the first digit, e.g., 123 is allowed but 0123 is not. You may assume that both integers are at most 6 digits in length. A line consisting of two zeros signals the end of the input.
Output
sum part1 part2 ...
rejected
error
In the first type, partj and sum have the following meaning :
1.Each partj is a number on one piece of shredded paper. The order of partj corresponds to the order of the original digits on the sheet of paper.
2.sum is the sum of the numbers after being shredded, i.e., sum = part1 + part2 +...
Each number should be separated by one space.
The message error is printed if it is not possible to make any combination, and rejected if there is
more than one possible combination.
No extra characters including spaces are allowed at the beginning of each line, nor at the end of each line.
Sample Input
50 12346
376 144139
927438 927438
18 3312
9 3142
25 1299
111 33333
103 862150
6 1104
0 0
Sample Output
43 1 2 34 6
283 144 139
927438 927438
18 3 3 12
error
21 1 2 9 9
rejected
103 86 2 15 0
rejected
Source
分析第一组样例:50 12346,其最优分解为1 2 34 6,和为43
第七组样例:111 33333,其最优分解为33 33 3或者3 33 33不唯一,故输出rejected
#include <cstdio> #include <cstring> int n, len, ans; char s[10]; bool rejected; bool mark[10], tmark[10]; //当前的和,当前数字的头下标,当前数字的尾下标 void DFS(int sum, int st, int ed) { if(sum > n) return; int cur = 0; for(int i = st; i < ed; i++) { cur *= 10; cur += (s[i] - '0'); } if(ed == len) { sum += cur; if(sum <= n && ans >= 0) { if(ans < sum) { ans = sum; rejected = false; for(int i = 0; i < len; i++) mark[i] = tmark[i]; } else if(sum == ans) rejected = true; } return; } tmark[ed] = false; DFS(sum, st, ed + 1); //不拆 tmark[ed] = true; DFS(sum + cur, ed, ed + 1) ;//拆 } int main() { int t; while(scanf("%d %d", &n, &t) && (n + t)) { rejected = false; int tmp = t, sum = 0; while(tmp) { sum += (tmp % 10); tmp /= 10; } if(sum > n) { printf("error\n"); continue; } if(n == t) { printf("%d %d\n", n, n); continue; } sprintf(s, "%d", t); len = strlen(s); ans = 0; tmark[0] = true; DFS(0, 0, 1); if(rejected) printf("rejected\n"); else if(ans > 0) { printf("%d", ans); for(int i = 0; i < len; i++) { if(mark[i]) printf(" "); printf("%c", s[i]); } printf("\n"); } } }
Time Limit: 2000MS | Memory Limit: 65536K | |||
Total Submissions: 14368 | Accepted: 7102 | Special Judge |
Description
Input
Output
Sample Input
1 103000509 002109400 000704000 300502006 060000050 700803004 000401000 009205800 804000107
Sample Output
143628579 572139468 986754231 391542786 468917352 725863914 237481695 619275843 854396127
Source
#include <cstdio> char s[10]; int num[9][9]; bool flag; bool ok(int n, int cur) { int r = n / 9; //当前行 int c = n % 9; //当前列 for(int j = 0; j < 9; j++) //枚举列 if (num[r][j] == cur) return false; for(int i = 0; i < 9; i++) //枚举行 if (num[i][c] == cur) return false; //得到当前所在的子矩阵的第一个元素位置 int x = r / 3 * 3; int y = c / 3 * 3; //枚举子矩阵中的元素 for(int i = x; i < x + 3; i++) for(int j = y; j < y + 3; j++) if (num[i][j] == cur) return false; return true; } void DFS(int n) { if(n > 80 || flag) { flag = true; return; } if(num[n / 9][n % 9])//当前位置有数字直接搜索下一位 { DFS(n + 1); if(flag) return; } else { for(int cur = 1; cur <= 9; cur++) //枚举数字 { if(ok(n, cur)) //若ok则插入 { num[n / 9][n % 9] = cur; DFS(n + 1); if(flag) return; num[n / 9][n % 9] = 0; //还原 } } } } int main() { int T; scanf("%d", &T); while(T--) { flag = false; for(int i = 0; i < 9; i++) //得到数独矩阵 { scanf("%s", s); for(int j = 0; j < 9; j++) num[i][j] = (s[j] - '0'); } DFS(0); //从第一位开始搜 for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) printf("%d", num[i][j]); printf("\n"); } } }
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 12678 | Accepted: 6498 |
Description
Since the radio frequency spectrum is a precious resource, the number of channels required by a given network of repeaters should be minimised. You have to write a program that reads in a description of a repeater network and determines the minimum number of channels required.
Input
Following the number of repeaters is a list of adjacency relationships. Each line has the form:
A:BCDH
which indicates that the repeaters B, C, D and H are adjacent to the repeater A. The first line describes those adjacent to repeater A, the second those adjacent to B, and so on for all of the repeaters. If a repeater is not adjacent to any other, its line has the form
A:
The repeaters are listed in alphabetical order.
Note that the adjacency is a symmetric relationship; if A is adjacent to B, then B is necessarily adjacent to A. Also, since the repeaters lie in a plane, the graph formed by connecting adjacent repeaters does not have any line segments that cross.
Output
Sample Input
2 A: B: 4 A:BC B:ACD C:ABD D:BC 4 A:BCD B:ACD C:ABD D:ABC 0
Sample Output
1 channel needed. 3 channels needed. 4 channels needed.
Source
#include<cstdio> #include<cstring> int map[30][30]; int color[30]; int n,col; bool flag; char s[30]; bool ok(int i) { //若与i直接相连的各点值均与i点值不同则返回true for(int j = 0; j < 26; j++) { if(!map[i][j]) continue; if(color[i] == color[j]) return false; } return true; } void dfs(int num) { if(num == n) //若num与n相等,则着色完毕 { flag = true; return; } for(int i = 1; i <= col; i++) //枚举col个数字用来标记 { color[num] = i; //赋值 if(ok(num)) //若当前赋值符合条件搜索下一个 dfs(num + 1); color[num] = 0; //还原 } } int main() { while(scanf("%d", &n) && n) { flag = false; memset(map, 0, sizeof(map)); for(int i = 0; i < n; i++) //构图 { scanf("%s", s); int len = strlen(s); for(int j = 2; j < len; j++) map[i][s[j]-'A'] = map[s[j]-'A'][i] = 1; } for(col = 1; col <= 4; col++) //根据四色定理枚举1-4,代表用几个数字可以标记完 { dfs(0); //从第一个字母开始搜索赋值 if(flag) break; } if(col == 1) printf("1 channel needed.\n"); else printf("%d channels needed.\n", col); } return 0; }
Q题 图的深度优先遍历序列
总提交 : 1083 测试通过 : 327
题目描述
图(graph)是数据结构 G=(V,E),其中V是G中结点的有限非空集合,结点的偶对称为边(edge);E是G中边的有限集合。设V={0,1,2,……,n-1},图中的结点又称为顶点(vertex),有向图(directed graph)指图中代表边的偶对是有序的,用<u,v>代表一条有向边(又称为弧),则u称为该边的始点(尾),v称为边的终点(头)。无向图(undirected graph)指图中代表边的偶对是无序的,在无向图中边(u,v )和(v,u)是同一条边。
输入边构成无向图,求以顶点0为起点的深度优先遍历序列。
输入
第一行为两个整数n、e,表示图顶点数和边数。以下e行每行两个整数,表示一条边的起点、终点,保证不重复、不失败。1≤n≤20,0≤e≤190
输出
前面n行输出无向图的邻接矩阵,最后一行输出以顶点0为起点的深度优先遍历序列,对于任一起点,首先遍历的是终点序号最小的、尚未被访问的一条边。每个序号后输出一个空格。
样例输入
4 5
0 1
0 3
1 2
1 3
2 3
样例输出
0 1 0 1
1 0 1 1
0 1 0 1
1 1 1 0
0 1 2 3
<span style="font-size:14px;">#include <cstdio> #include <cstring> int map[25][25]; bool vis[25]; int n, e; void DFS(int a) { vis[a] = true; printf("%d ", a); for(int i = 0; i < n; i++) if(map[a][i] && !vis[i]) DFS(i); } int main() { int x, y; scanf("%d %d", &n, &e); memset(map, 0, sizeof(map)); memset(vis, false, sizeof(vis)); for(int i = 0; i < e; i++) { scanf("%d %d", &x, &y); map[x][y] = 1; map[y][x] = 1; } for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) printf("%d ", map[i][j]); printf("\n"); } for(int i = 0; i < n; i++) if(!vis[i]) DFS(i); printf("\n"); }</span>
基础搜索算法题解(N-R)