2016年中国大学生程序设计竞赛 CCPC (杭州)
A - ArcSoft's Office Rearrangement HDU - 5933
题意:
给你n个数,你有两个操作:1.将相邻两个数合并 2.将一个数拆分成两个数
求将这n个数变成k个相同的数最小操作数。
思路
实际上要变为k个相同的数,每次的合并和分解都是必要的,那么可以直接先合并后分解。
#include <bits/stdc++.h> //#pragma GCC optimize(3) //如果有STL,开O3 #define endl '\n' #define pii pair<int,int> #define int long long using namespace std; const int N = 1e5 + 10; int t, n, k, a[N], cnt, sum,ans= 0, ave,tt, tot; void solve(){ cin >> t; while(t -- ){ tt ++; cin >> n >> k; ans = 0; cnt = 0; for(int i = 1; i <= n; i++){ cin >> a[i]; ans += a[i]; } sum = 0; if(ans % k == 0){ ave = ans / k; for(int i = 1; i <= n; i++){ sum += a[i]; if(sum % ave == 0){ cnt += tot + (sum / ave - 1); tot = 0; sum = 0; } else{ tot ++; } } cout <<"Case #"<<tt<<": " <<cnt << endl; } else{ cout <<"Case #"<<tt<<": " <<-1 << endl; } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); solve(); return 0; }
B - Bomb HDU - 5934 强连通分量tarjan
题意:
给出n个炸弹的坐标(x,y)、爆炸能辐射成一个圆的半径r和引爆该炸弹需要的代价c,
且某一个炸弹爆炸后,无需要代价直接引爆在能辐射圆内的炸弹,
问如何引爆所有炸弹需要的最小代价。
思路:
做题先是想到了dp,后来又想到了并查集,后来发现都解决不了。A可以引爆B但是,B不一定引爆A的问题。
后来想到了强连通分量:
- 将可以相互引爆的进行缩点;
(因为无论选择谁都可以连环炸) - 然后对缩后的点建立有向边;
建立的图一定是棵树(或者是森林) - 然后只需要选择所有树的根节点即可。
因为是有向边,选择其他的点也需要再选择根节点,但是选择就可以连环炸掉他的所有子树。
代码:
错误代码(超时了)
超时原因:
写了一个check函数,因为check的参数是Node,
调用时会很慢.....具体也不清楚队友说的。 下次注意了。- 初始化时用的memset(x,0,sizeof x),每次会初始化整个数组
- 使用了函数pow
void init(){ } struct Node { int x,y; int r,val; }a[N]; bool check(Node q,Node p){ int len=pow(abs(q.x-p.x),2)+pow(abs(q.y-p.y),2); if(len>(q.r*q.r)) return false; else return true; } void tarjan(int u){ } int xxx; void slove(){ } signed main() { }
正确代码:
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define int long long const int N = 1010; const int M = 2e6 + 10; int n; int to[M], pre[M], h[N], idx; int dfn[N], low[N], temp; int id[N], scc_cnt, scc_size[N], scc_min[N]; int stk[N], top; bool in_stk[N]; int d[N]; void init() { for (int i = 0; i <= n; i++) h[i] = -1; for (int i = 0; i <= n; i++) scc_min[i] = 0x3f3f3f3f3f; for (int i = 0; i <= n; i++) in_stk[i] = false; for (int i = 0; i <= n; i++) d[i] = 0; for (int i = 0; i <= n; i++) dfn[i] = 0; for (int i = 0; i <= n; i++) low[i] = 0; top = 0; idx = 0; scc_cnt = 0; temp = 0; } struct Node { int x, y; int r, val; } a[N]; void add(int x, int y) { to[idx] = y, pre[idx] = h[x], h[x] = idx++; } void tarjan(int u) { dfn[u] = low[u] = ++temp; stk[++top] = u; in_stk[u] = true; for (int i = h[u]; i != -1; i = pre[i]) { int j = to[i]; if (!dfn[j]) { tarjan(j); low[u] = min(low[u], low[j]); } else if (in_stk[j]) low[u] = min(low[u], dfn[j]); } if (low[u] == dfn[u]) { int y; scc_cnt++; do { y = stk[top--]; in_stk[y] = false; id[y] = scc_cnt; scc_size[scc_cnt]++; scc_min[scc_cnt] = min(a[y].val, scc_min[scc_cnt]); } while (y != u); } } bool check(int i, int j) { int len = (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y); if (len > (a[i].r * a[i].r)) return false; else return true; } int xxx; void slove() { cin >> n; init(); for (int i = 0; i < n; i++) { cin >> a[i].x >> a[i].y >> a[i].r >> a[i].val; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) continue; if (check(i, j)) add(i, j); } } for (int i = 0; i < n; i++) { if (!dfn[i]) tarjan(i); } for (int i = 0; i < n; i++) { for (int j = h[i]; j != -1; j = pre[j]) { int y = to[j]; if (id[i] != id[y]) d[id[y]]++; } } int cnt = 0; for (int i = 1; i <= scc_cnt; i++) { if (!d[i]) { cnt += scc_min[i]; } } printf("Case #%lld: %lld\n", ++xxx, cnt); } signed main() { int t; cin >> t; while (t--) { slove(); } return 0; }
C - Car HDU - 5935
题意:
车子从起始位置 0开始到达终点一共有 N 个位置被标记,每个位置被标记的时间都是整数时间,并且车子只能做加速运动和匀速运动。问,车子最短时间达到终点的时间花费。
思路:
逆向贪心模拟,最好一段肯定是一秒花费,根据这个速度来往前推,速度不严格递减,保证每段时间是整数。看代码吧
因为速度是小数,为了避免精度丢失,采用分数形式来表示。
代码
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define int long long const int N = 1e5+10; const int M = 2e6 + 10; int n; int a[N]; int case_=1; void slove() { scanf("%lld", &n); a[0]=0; for(int i=1;i<=n;i++){ scanf("%lld", &a[i]); } int ans=1; int p=a[n]-a[n-1],q=1; for(int i=n-1;i>=1;i--){ int dis=a[i]-a[i-1]; q*=dis; swap(p,q); int t=ceil(1.0*p/q); ans+=t; p=dis,q=t; } printf("Case #%lld: %lld\n", case_++, ans); } signed main() { int t; scanf("%lld", &t); while (t--) slove(); return 0; }
# F - Four Operations HDU - 5938
题意:
给你一个只有“1~9”数字的字符串,求按顺序插入“+”,“-”,“*”,“/”后,算式能够得到的最大值。
思路 贪心,看代码吧
#include <bits/stdc++.h> //#pragma GCC optimize(3) //如果有STL,开O3 #define endl '\n' #define pii pair<int,int> #define int long long using namespace std; const int N = 1e5 + 10; int t, ans, tt; int max(int a, int b){ if(a > b) return a; else return b; } void solve(){ cin >> t; while(t -- ){ string st; // st = "0"; tt ++; cin >> st; if(st.size() == 5){ cout <<"Case #"<<tt<<": "; cout << (st[0] -'0') + ( st[1] -'0') - (st[2] - '0') * (st[3] - '0') / (st[4] - '0') << endl; } else{ int len = st.size() - 1; //last int s4 = st[len] - '0'; int s3 = st[len - 1] - '0'; int s2 = st[len - 2] - '0'; int s1 = 0; if(len - 3 >= 2){ int u = st[0] - '0'; int v = 0; for(int i = 1; i <= len - 3; i ++){ v = v * 10 + (st[i] - '0'); } // cout << u <<" - " << v << endl; s1 = u + v; //cout <<"?" << s1 << endl; u = st[len - 3] - '0'; v = 0; for(int i = 0; i <= len - 4; i ++){ v = v * 10 + (st[i] - '0'); } s1 = max(s1, u + v); ans = s1 - s2 * s3 / s4; // cout <<s1 <<" "<<s2 <<" " << s3 <<" "<<s4 <<endl; // cout << 1 <<" " << ans << endl; } else{ s1 = st[0] -'0' + (st[1] - '0'); ans = s1 - s2 * s3 / s4; //cout << 1 <<" " << ans << endl; } //last1 s4 = (st[len - 1] - '0') * 10 + (st[len] - '0'); s3 = st[len - 2] -'0'; s2 = st[len - 3] - '0'; if(len - 4 >= 2){ int u = st[0] - '0'; int v = 0; for(int i = 1; i <= len - 4; i ++){ v = v * 10 + (st[i] - '0'); } s1 = u + v; u = st[len - 4] - '0'; v = 0; for(int i = 0; i <= len - 5; i ++){ v = v * 10 + (st[i] - '0'); } s1 = max(s1, u + v); ans = max(ans, s1 - s2 * s3 / s4); //cout << 2 <<" " << ans << endl; } else{ s1 = st[0] -'0' + (st[1] - '0'); ans = max(ans,s1 - s2 * s3 / s4); //cout << 2 <<" " << ans << endl; } cout <<"Case #"<<tt<<": " << ans << endl; } } } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); solve(); return 0; }
本文作者:kingwzun
本文链接:https://www.cnblogs.com/kingwz/p/16480103.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步