CF拉练第一场
来源:互联网 发布:淘宝重量运费模板 编辑:程序博客网 时间:2024/04/28 16:01
练习赛1
题目源地址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=61581#overview
- Problem A Before an Exam (水题)
- Problem B The least round way (DP)
- Problem C Tic-tac-toe (模拟)
- Problem D Ancient Berland Circus (几何)
- Problem E Least Cost Bracket Sequence (贪心)
Problem A Before an Exam
给定
思路
求一下最小值和,最大值和,如果sum在之间,一定满足。
AC代码
#include <cstdio>#include <algorithm>#include <iostream>using namespace std;int main(){ int d, sumtime, maxn, minn, x[100], y[100]; cin >> d >> sumtime; maxn = 0; for(int i = 0; i < d; i++) { cin >> x[i] >> y[i]; minn += x[i]; maxn += y[i]; } if(maxn < sumtime || minn > sumtime) { printf("NO\n"); return 0; } int delta = maxn - sumtime; for(int i = 0; i < d; i++) { if(y[i] - x[i] >= delta) { y[i] -= delta; break; } else { delta -= y[i] - x[i]; y[i] = x[i]; } } printf("YES\n"); for(int i = 0; i < d; i++) printf("%d ", y[i]); return 0;}
Problem B The least round way
思路
对于每一个数字,进行处理,我们只需要知道这个数字分别能被2、5整除多少次。
第一次走的时候,保证取2最小,(2一样的时候,5要最小),且在走的过程中记录路径。
然后再走一次,保证取5最小,(5一样的时候,2要最小),且在走的过程中记录路径。
最后的答案就是上面两个的最小值。
trick:有可能有数字为0,那乘积为0,答案为1,否则上述得到的最小值大于1,那么便不取,而是选择走0那条路径。
AC代码
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#include <functional>#include <stdarg.h>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-4)#define inf (1<<28)#define ll long long intusing namespace std;int mat[1005][1005];char direct[1005][1005][2]; //分别记录2,5整除次数最少的路径用D,R表示int dp[1005][1005][2]; //分别记录矩阵中每个数能被2,5整除的次数char path[2010];int path_len;int factors(int num, int base) { int ret = 0; int fct = base; if(num == 0) return 1; while(num % fct == 0) { ret++; fct *= base; //除数乘以base和被除数除以base一样 } return ret;}int mi(int a, int b){ return a < b ? a : b;}int main(){ int n; scanf("%d", &n); bool zero = false; //判断矩阵中是否有0 int zero_i; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { scanf("%d", &mat[i][j]); if(mat[i][j] == 0) { zero = true; zero_i = i; //记录其中一个0所在的行 } dp[i][j][0] = factors(mat[i][j], 2); dp[i][j][1] = factors(mat[i][j], 5); } } for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { for(int k = 0; k < 2; k++) //记录从起点到该点的最小次数,同时记录路径 { if(i == 0 && j == 0) continue; if(i == 0) { dp[i][j][k] += dp[i][j - 1][k]; direct[i][j][k] = 'R'; } else if(j == 0) { dp[i][j][k] += dp[i - 1][j][k]; direct[i][j][k] = 'D'; } else { dp[i][j][k] += dp[i - 1][j][k] < dp[i][j - 1][k] ? dp[i - 1][j][k] : dp[i][j - 1][k]; direct[i][j][k] = dp[i - 1][j][k] < dp[i][j - 1][k] ? 'D' : 'R'; } } } } if(mi(dp[n - 1][n - 1][0], dp[n - 1][n - 1][1]) > 1 && zero) { printf("1\n"); for(int i = 0; i < zero_i; i++) printf("D"); for(int i = 0; i < n - 1; i++) printf("R"); for(int i = zero_i; i < n - 1; i++) printf("D"); } else { printf("%d\n", mi(dp[n - 1][n - 1][0], dp[n - 1][n - 1][1])); path_len = 0; int k = 1; if(dp[n - 1][n - 1][0] < dp[n - 1][n - 1][1]) k = 0; for(int i = n - 1, j = n - 1; i != 0 || j != 0; ) { path[path_len++] = direct[i][j][k]; if(direct[i][j][k] == 'D') { i--; } else if(direct[i][j][k] == 'R') { j--; } } for(int i = 2 * (n - 1) - 1; i >= 0; i--) printf("%c", path[i]); } printf("\n"); return 0;}
Problem C Tic-tac-toe
3 X 3的棋盘,井字棋游戏,两个人连续在棋盘上放棋子(第一个人为X,第二个人为0),如果出现某行某列或者对角线上全为同样的棋子,那么该人获胜。
现在给出当下棋盘状态,让判断是那种状态
- illegal 棋盘情况不合法
- the first player won 第一个人赢
- the second player won 第二个人赢
- draw 平局
- first 轮到第一个人走
- second 轮到第二个人走 -
思路
主要illegal的情况比较多:
- 双方棋子数不符合规则
- 双方都赢了
- 先手赢了,后手还放棋子
- 后手赢了,先手还放棋子
AC代码
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-4)#define inf (1<<28)#define ll long long intusing namespace std;int xcnt, ocnt, num3;char gao[3][3];bool win(char tmp) //用函数表示会简单一些,我之前写的太挫了{ for(int i = 0; i < 3; i++) { if(gao[i][0] == tmp && gao[i][1] == tmp && gao[i][2] == tmp) return true; if(gao[0][i] == tmp && gao[1][i] == tmp && gao[2][i] == tmp) return true; } if(gao[1][1] != tmp) return false; if(gao[0][0] == tmp && gao[2][2] == tmp) return true; if(gao[2][0] == tmp && gao[0][2] == tmp) return true; return false;}bool legal(){ for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { xcnt += gao[i][j] == 'X'; ocnt += gao[i][j] == '0'; } } if(xcnt < ocnt || xcnt - ocnt > 1) return false; if(win('X') && xcnt == ocnt) return false; if(win'X' && win'0') return false; if(win('0') && xcnt != ocnt) return false; return true;}int main(){ xcnt = 0; ocnt = 0; for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++) cin >> gao[i][j]; if(!legal()) //判断非法 { printf("illegal\n"); return 0; } if(win('X')) //判断赢家 { printf("the first player won\n"); return 0; } if(win('0')) { printf("the second player won\n"); return 0; } if(xcnt + ocnt == 9) //判断平局 { printf("draw\n"); return 0; } if(xcnt == ocnt) //判断先后手 { printf("first\n"); return 0; } if(xcnt - ocnt == 1) { printf("second\n"); return 0; }}
Problem D Ancient Berland Circus
几何题,有一个正多边形(3<=n<=100),给出其中的三个顶点,问这个正多边形最小可能的面积。
思路
最小面积的话,就是要求正多边形的边数尽量少,给出三个点,可以求出外接圆
AC代码
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-4)#define inf (1<<28)#define ll long long intusing namespace std;double a, b, c, r, q, s;double A, B, C, angle, ans, n;struct node{ double x, y;}piller[3];double dis(node a, node b) //计算两点间的距离{ return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));}double fgcd(double a, double b) //实型求余fmod函数,fgcd求出实数a,b的(近似)最大公约数{ if(fabs(b - 0) <= eps) return a; return fgcd(b, fmod(a, b));}void init(){ memset(piller, 0, sizeof(piller)); for(int i = 0; i < 3; i++) { scanf("%lf%lf", &piller[i].x, &piller[i].y); } a = dis(piller[0], piller[1]); b = dis(piller[1], piller[2]); c = dis(piller[2], piller[0]); q = (a + b + c) / 2; //海伦公式 s = sqrt(q * (q - a) * (q - b) * (q - c)); r = a * b * c / (4 * s); A = acos(1 - a * a / r / r / 2); B = acos(1 - b * b / r / r / 2); C = 2 * pi - A - B;}int main(){ init(); ans = pi / fgcd(A, fgcd(B, C)) * r * r * sin(fgcd(A, fgcd(B, C))); printf("%.8lf\n", ans); return 0;}
Problem E Least Cost Bracket Sequence
有一串字符串,每个字符为’(‘, ‘)’ 或’?’。现在需要将其中的’?’替换为’(‘或’)’,使得最后所有括号能匹配。每个’?’替换成相应的括号都有一个花费。如果最后不能匹配,输出-1。否则输出最少的花费。
思路
优先队列的用法,cnt 记录了‘(’和‘)’的匹配状况,‘?’先当作‘)’处理,遇到‘(’cnt++,遇到')'cnt--;遇到‘?’时cnt--,同时输入两个取代值a,b,并将b - a,和当前位置配对存入优先队列 ,如果遇到cnt<0时,队列中踢出一组 即 之前当作‘)’处理的‘?’现在当作‘(’处理,cnt += 2,同时ss权值减去此处a, b 的差;如果此时没有备用的‘?’则不符合要求,输出-1;
AC代码
#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <string>#include <vector>#include <deque>#include <list>#include <set>#include <map>#include <stack>#include <queue>#include <numeric>#include <iomanip>#include <bitset>#include <sstream>#include <fstream>#define debug "output for debug\n"#define pi (acos(-1.0))#define eps (1e-8)#define inf 0x3f3f3f3f#define ll long long intusing namespace std;#define MAXN 50000+10char s[MAXN];ll ss;int cnt;int a, b;priority_queue<pair<ll, int> > que;int main(){ scanf("%s", s + 1); ss = 0; cnt = 0; for(int i = 1; s[i]; i++) { if(s[i] == '(') { cnt++; } else if(s[i] == ')') { cnt--; } else { scanf("%d%d", &a, &b); ss += b; cnt--; s[i] = ')'; que.push(pair<ll, int> (b - a, i)); } if(cnt < 0) { if(que.empty()) break; pair<ll, int> f = que.top(); que.pop(); ss -= f.first; cnt += 2; s[f.second] = '('; } } if(cnt != 0) printf("-1\n"); else printf("%lld\n%s\n", ss, s + 1); return 0;}
- CF拉练第一场
- 第一场cf
- 我的第一场CF小结
- 下午拉练
- CodeForces--ZeptoLab Code Rush 2015 (我参加的第一场cf比赛)
- 最近两场cf总结
- 第一场雪
- 北京第一场雪
- 南京第一场雪
- 第一场雪
- 2010第一场雪
- 第一场雪@杭州
- 第一场笔试感悟
- Astar第一场
- 人生第一场regional
- 超图篮球联赛第一场
- 记多校第一场
- 第一场总结
- bug report的三要素
- sshd_localhost出错:Connection closed by ::1
- Linux设备驱动子系统第四弹 - USB Gadget
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
- 详解物化视图(汇总比较有用的资料)
- CF拉练第一场
- poj 2186 Popular Cows 【强连通】
- oracle:could not locate oci.dll
- 黑马程序员 学习日志05 异常
- Android Volley完全解析(三),定制自己的Request
- HDU—— 4932 Miaomiao's Geometry
- Openvswitch手册(4): Mirror
- Spring MVC 中 HandlerInterceptorAdapter的使用
- dedecms增加php函数功能及在列表页获取当前栏目的文章数