标签:
A:点击打开链接
CSU 1561 (More)Multiplication
题意:把两个数的乘积每个位置的结果填充上去。
注意这个矩阵最大是1e8,所以不能开数组。
模拟题
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; typedef long long ll; const int N = 10005; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } int ans[N * 2]; char A[N], B[N]; char a[N * 4]; int main() { while (~scanf("%s %s", A, B)) { int m = strlen(A), n = strlen(B), x = 0, y = 0; for (int i = 0; i < m; i++) { x = x * 10 + (A[i] - '0'); } for (int i = 0; i < n; i++) { y = y * 10 + (B[i] - '0'); } if (x == 0 && y == 0) break; int num = x*y, size = 0; while (num > 0) { ans[size++] = num % 10; num /= 10; } while (size < n + m) { ans[size++] = -1; } n = n * 4 + 5; m = m * 4 + 5; bool f = false; for (int ii = 0; ii < n; ii++) { a[m] = '\0'; for (int jj = 0; jj < m; jj++) a[jj] = ' '; if (ii == 0 || ii == n - 1) { a[0] = a[m - 1] = '+'; for (int jj = 1; jj < m - 1; jj++) { a[jj] = '-'; } } else { a[0] = a[m - 1] = '|'; if (ii == 1) { for (int j = 4; j < m - 1; j += 4) { a[j] = A[j / 4 - 1]; } } else if (ii == n - 2) { for (int pos = m - 6, id = 0; pos > 0; pos -= 4, id++) { a[pos] = ans[id] + '0'; a[pos - 2] = '/'; } if (!f) a[1] = ' '; } else { if ((ii - 2) % 4 == 0) { for (int j = 2; j < m - 2; j++) { if ((j - 2) % 4 == 0) a[j] = '+'; else a[j] = '-'; } } else { for (int j = 2; j < m - 2; j += 4) { a[j] = '|'; } if ((ii + 1) % 4 == 0) { if (f) a[1] = '/'; for (int j = 4; j < m - 1; j += 4) { a[j + 1] = '/'; a[j - 1] = (A[j / 4 - 1] - '0') * (B[(ii + 1) / 4 - 1] - '0') / 10 + '0'; } } if (ii % 4 == 0) { for (int j = 4; j < m - 1; j += 4) { a[j] = '/'; } a[m - 2] = B[ii / 4 - 1]; } if ((ii - 1) % 4 == 0) { if (ans[size - 1] != -1) { a[1] = ans[size - 1] + '0'; f = true; } size--; for (int j = 4; j < m - 1; j += 4) { a[j - 1] = '/'; a[j + 1] = (A[j / 4 - 1] - '0') * (B[(ii - 1) / 4 - 1] - '0') % 10 + '0'; } } } } } printf("%s\n", a); } } return 0; }B:点击打开链接
题意:
给定一个矩阵,矩阵内部有2种镜子/ \,从边缘的*入射一条光线,则光线一定会射到边缘,把边缘用&标记。
然后输出这个矩阵。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; const int MAX_N = 27; int n, m; int ex, ey; char maz[27][27]; bool vis[MAX_N][MAX_N]; bool found; bool safe(int x, int y) { return x >= 0 && x < m && y >= 0 && y < n; } void dfs(int x, int y, int dir) { if (found) return ; if (dir == 1) ++x; else if (dir == 2) ++y; else if (dir == 3) --x; else --y; if (safe(x, y)) { if (maz[x][y] == 'x') { ex = x, ey = y; found = true; return ; } if (maz[x][y] == '.') dfs(x, y, dir); else if (maz[x][y] == '/') { if (dir == 1) { dfs(x, y, 4); } else if (dir == 2) { dfs(x, y, 3); } else if (dir == 3) { dfs(x, y, 2); } else { dfs(x, y, 1); } } else { if (dir == 1) { dfs(x, y, 2); } else if (dir == 2) { dfs(x, y, 1); } else if (dir == 3) { dfs(x, y, 4); } else { dfs(x, y, 3); } } } } void Clear() { ex = 0, ey = 0; found = false; memset(maz, 0, sizeof maz); } int main() { int cas = 0; while (2 == scanf("%d%d", &n, &m)) { if (0 == n && 0 == m) break; int sx = 0, sy = 0; Clear(); for (int i = 0; i < m; ++i) { scanf("%s", maz[i]); for (int j = 0; j < n; ++j) { if (maz[i][j] == '*') { sx = i, sy = j; maz[i][j] = '.'; } } } if (sx == 0) dfs(sx, sy, 1); else if (sx == m-1) dfs(sx, sy, 3); else if (sy == 0) dfs(sx, sy, 2); else dfs(sx, sy, 4); printf("HOUSE %d\n", ++cas); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (i == sx && j == sy) { putchar('*'); } else if (i == ex && j == ey) { putchar('&'); } else putchar(maz[i][j]); } puts(""); } } return 0; }C:点击打开链接
给定一个字符串,问字典序第k小的是什么。
从高位到低位枚举,每次填充排列数<=k且最大的那个字母。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; typedef long long ll; const int N = 20; char s[N], t[N]; ll k; ll num[27]; ll J[30]; int len; ll way(){ ll sum = 0; for(int i = 0; i < 26; i++)sum += num[i]; ll ans = J[sum]; for(int i= 0; i < 26; i++)ans /= J[num[i]]; return ans; } void dfs(int now , ll pre){ if(now == len)return ; char c = 'A'; for(int i = 0; i < 26; i++){ if(num[i]==0)continue; c = 'A'+i; num[i]--; ll hehe = way(); num[i]++; if(pre + hehe >= k){ break; } pre += hehe; } num[c-'A']--; t[now] = c; dfs(now+1, pre); } int main() { J[0] = 1; for(ll i = 1; i < 30; i++)J[i] = J[i-1]*i; while (~scanf("%s", s)) { cin>>k; if(s[0] == '#' && k==0)break; memset(num, 0, sizeof num); len = strlen(s); memset(t, 0, sizeof t); for(int i = 0; s[i]; i++)num[s[i]-'A'] ++; dfs(0, 0); puts(t); } return 0; }
CSU 1565 Word Cloud
某模拟题。
给出矩阵的宽度为P, N个字母。
下面给出每个字母和它的高度。
用题目中的图求出这个字母的宽度。
把字母从上到下,从左到右依次填充进矩阵,问填充完后矩阵的高度是多少
注意字母间距离是 10px
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; const int MAX_N = 107; int w, n; char str[100007]; int c[MAX_N], len[MAX_N]; int H[MAX_N], W[MAX_N]; int main() { int cas = 0; while (2 == scanf("%d%d", &w, &n)) { if (0 == w && 0 == n) break; int Cmax = 0; for (int i = 0; i < n; ++i) { scanf("%s%d", str, &c[i]); Cmax = max(Cmax, c[i]); len[i] = strlen(str); } for (int i = 0; i < n; ++i) { H[i] = 8 + ceil(40 * (c[i] - 4) * 1. / (Cmax - 4)); W[i] = ceil(9. * len[i] * H[i] / 16); } long long ans = 0, sum = 0; bool row = false; int maxH = 0; w += 10; for (int i = 0; i < n; ++i) { if (row) { row = false; ans += maxH; sum = 0; maxH = 0; } if (sum + W[i] + 10 <= w) { maxH = max(maxH, H[i]); sum += W[i] + 10; } else row = true, --i; } if (sum != 0) ans += maxH; printf("CLOUD %d: %lld\n", ++cas, ans); } return 0; }F:点击打开链接
给定一个迷宫的图,每个格子有16种形态,用一个16进制数表示。
边缘有且仅有2个缺口。
问:
if 2个缺口不连通则输出"No solution"
else if 存在点是不可达的则输出“Unreachable cell"
else if 2个缺口间存在不同的路径则输出 "Multiple path"
else "Maze ok"
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N = 55; int n, m; vector<int>G[N*N], path; vector<pii>D; int has(int x, int y){return x*m+y;} void add(int x, int y, int i, int j){ G[has(x,y)].push_back(has(i,j)); } int getx(int val){return val/m;} int gety(int val){return val%m;} bool inmap(int x, int y){ return 0<=x && x < n && 0<=y&&y<m; } char s[N]; int mp[N][N]; int step[4][2] = {0,-1, 1,0, 0,1, -1,0}; bool vis[N][N]; void bfs(int x, int y){ memset(vis, 0, sizeof vis); queue<int>q; q.push(has(x,y)); vis[x][y] = true; while(!q.empty()){ int u = q.front(); q.pop(); for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; x = getx(v); y = gety(v); if(vis[x][y])continue; vis[x][y] = true; q.push(v); } } } int solve(){ if(false == vis[D[1].first][D[1].second])return 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(false == vis[i][j])return 1; int siz = 0; for(int i = 0; i < n; i++)for(int j = 0; j < m; j++)siz += G[has(i,j)].size(); if((siz>>1)==n*m-1)return 3; return 2; } int main() { while (~scanf("%d %d", &n, &m), n+m) { D.clear(); for(int i = 0; i < n; i++){ scanf("%s", s); for(int j = 0; j < m; j++) { G[has(i,j)].clear(); if('0' <= s[j] && s[j]<='9')mp[i][j] = s[j]-'0'; else mp[i][j] = s[j]-'A'+10; } } for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) for(int k = 0; k < 4; k++) { int x = i+step[k][0], y = j+step[k][1]; if(!inmap(x,y)){ if((mp[i][j]&(1<<k))==0) D.push_back(pii(i,j)); continue; } if((mp[i][j]&(1<<k))==0) add(i,j, x,y); } sort(D.begin(), D.end()); D.erase(unique(D.begin(), D.end()), D.end()); if((int)D.size()==1) D.push_back(D[0]); bfs(D[0].first, D[0].second); int ans = solve(); if(ans == 0)puts("NO SOLUTION"); else if(ans == 1) puts("UNREACHABLE CELL"); else if(ans == 2)puts("MULTIPLE PATHS"); else puts("MAZE OK"); } return 0; } /* 1 8 2AAAAAAE */G:点击打开链接
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; const int MAX_N = 57; const char table[30] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_."; int n; char str[MAX_N]; int ID(char ch) { for (int i = 0; table[i]; ++i) if (table[i] == ch) return i; } int main() { while (1 == scanf("%d", &n)) { if (0 == n) break; scanf("%s", str); for (int i = 0; str[i]; ++i) { str[i] = table[(ID(str[i]) + n) % 28]; } int len = strlen(str); for (int i = len - 1; i >= 0; --i) { putchar(str[i]); } puts(""); } return 0; }H:点击打开链接
CSU 1568 Shrine Maintenance
题意:输入M N, D 后面D个数
把一个半径为1000的圆N等分,再利用圆上N个点中的所有有效点画出恰好M个类三角形(我想说的是一个类三角形和圆心相连的边恰好有两条哟,即使第二图中只有一个点相连)
有效点:我们给圆中的点编号(1~N) ,那么是D个数中任意一个数的倍数 就是有效点。
问:
使得画出的M个类三角形中 最大的周长最小。 输出那个周长, 保留一位小数。
思路:
二分答案判可行。
我们把相邻的有效点两两相连
W的作用相当于是 断开了W条有效边
假设W=0,那么应该是所有边长相连,所以是一个环。
开始的做法是枚举环的第一个断点,但这样会t
而我们发现前面的因子间隔比较大,达到lcm后间隔就相同,这样断开任意一边都是等效的。也就是说枚举前面的因子即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <map> #include <vector> using namespace std; const int MAX_N = 8607; int W, N, D; int cnt; bool vis[MAX_N]; int id[MAX_N]; void Clear() { cnt = 0; memset(vis, false, sizeof vis); } double get(int i, int j) { return 2000. * sin(acos(-1.) * abs(id[j] - id[i]) / N); } bool check(double ans, int j) { int w = W; double sum = 0; for (int i = (j+2)%cnt; ; i = (i+1)%cnt) { double now = get((i - 1+cnt)%cnt, i); if (sum + now <= ans) { sum += now; } else { sum = 0; --w; if (w < 0) return false; } if(i==j)break; } return true; } int main() { while (1 == scanf("%d", &W)) { if (0 == W) break; Clear(); scanf("%d%d", &N, &D); for (int i = 0; i < D; ++i) { int v; scanf("%d", &v); for (int j = v; j <= N; j += v) vis[j] = true; } for (int i = 1; i <= N; ++i) if (vis[i]) id[cnt++] = i; if(cnt <= W) { puts("2000.0"); continue; } if(W == 0){ puts("0.0"); continue; } W--; double ans = 1e8; for(int j = 0; j < min(100,cnt); j++){ double l = 0, r = ans; for (int i = 0; i <30; ++i) { double mid = (l + r) / 2; if (check(mid, j)) r = mid; else l = mid; } ans = min(ans, r); } printf("%.1f\n", ans + 2000); } return 0; }
CSU 1569 Wet Tiles
给定n*m的矩阵 时刻t L个起点 W个墙
下面给出L个点的坐标
下面每4个数字给出每个墙的起点终点(墙要么平行于轴,要么45°倾斜)
问每个点bfs出去t下后,整个图被遍历了多少点。
简单bfs
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; typedef pair<int, int> pii; const int N = 1005; char mp[N][N]; int vis[N][N]; int n, m, T; queue<pii> que; const int dx[] = {0, 0, -1, 1}; const int dy[] = {-1, 1, 0, 0}; int bfs() { int ans = 0; while(que.size() > 0) { pii tmp = que.front(); que.pop(); int x = tmp.first, y = tmp.second; ans ++; if(vis[x][y] == T) continue; for(int i = 0; i < 4; i ++) { int nx = x + dx[i]; int ny = y + dy[i]; if(nx >= 0 && nx < n && ny >= 0 && ny < m && vis[nx][ny] == 0) { vis[nx][ny] = vis[x][y] + 1; que.push(make_pair(nx, ny)); } } } return ans; } int main() { while(~scanf("%d", &m)) { if(m == -1) break; memset(vis, 0, sizeof vis); int L, W; scanf("%d%d%d%d", &n, &T, &L, &W); for(int i = 0, x, y; i < L; i ++) { scanf("%d%d", &x, &y); swap(x, y); y--, x = n - x; que.push(make_pair(x, y)); vis[x][y] = 1; } for(int i = 0, x1, x2, y1, y2; i < W; i ++) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); swap(x1, y1); swap(x2, y2); y1--, y2--; x1 = n - x1; x2 = n - x2; if(x1 == x2) { if(y1 < y2) { while(y1 <= y2) { vis[x1][y1++] = -1; } } else { while(y1 >= y2) { vis[x1][y1--] = -1; } } } else if(y1 == y2) { if(x1 < x2) { while(x1 <= x2) { vis[x1++][y1] = -1; } } else { while(x1 >= x2) { vis[x1--][y1] = -1; } } } else { if(x1 < x2) { if(y1 < y2) { while(x1 <= x2) { vis[x1++][y1++] = -1; } } else { while(x1 <= x2) { vis[x1++][y1--] = -1; } } } else { if(y1 < y2) { while(x1 >= x2) { vis[x1--][y1++] = -1; } } else { while(x1 >= x2) { vis[x1--][y1--] = -1; } } } } } printf("%d\n", bfs()); } return 0; }
湖南多校对抗赛(2015.4.6)CSU 1561~1569 题解
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/45128101