赞
踩
这几天主要在写robocom的题,写了个初赛就自闭了,我怎么可以这么菜啊。
7-1 懂的都懂(20分)
题意:设n个非负整数和k次询问,每一次询问中的m个数字是否都是n个非负整数中其中四个数字的平均值,是的话输出Yes,否则输出No。
题目特征:n个数中选4个数,并且要对这个结果进行处理。
思路:dfs,搜到四个数就停下来,把平均值用map存起来,记得要回溯。我写代码的时候采用的是固定一个数,然后去搜剩下的三个数,但其实搜四个数也是一样的。(第一反应居然是全排列,蓝桥杯打傻了
- 1. #include<bits/stdc++.h>
- 2. using namespace std;
- 3. int n, k, a[55], vis[55];
- 4. map<int, int> mp;
- 5. void dfs(int num, int sum, int kk){
- 6. if(num == 4){ //选够四个数
- 7. if(sum % 4 == 0) mp[sum / 4] = 1; //因为输进来的都是整数,所以确定模4等于0之后才能存入
- 8. return;
- 9. }
- 10. vis[kk] = 1;
- 11. for(int i = 0; i < n; i++){
- 12. if(!vis[i]){
- 13. dfs(num + 1, sum + a[i], i);
- 14. }
- 15. }
- 16. vis[kk] = 0; //回溯
- 17. }
- 18. int main(){
- 19. ios::sync_with_stdio(false);
- 20. cin.tie(0);
- 21. cin >> n >> k;
- 22. int kk = 0;
- 23. for(int i = 0; i < n; i++){
- 24. cin >> a[i];
- 25. }
- 26. sort(a, a + n);
- 27. for(int i = 0; i < n; i++){
- 28. dfs(1, a[i], i);
- 29. }
- 30. // for(auto it = mp.begin(); it != mp.end(); it++){
- 31. // printf("****%d\n", (*it).first);
- 32. // }
- 33. for(int i = 0; i < k; i++){
- 34. int flag = 0;
- 35. int x; cin >> x;
- 36. for(int j = 0; j < x; j++){
- 37. int g; cin >> g;
- 38. if(!mp[g]) flag = 1;
- 39. }
- 40. if(!flag) printf("Yes\n");
- 41. else printf("No\n");
- 42. }
- 43. return 0;
- 44. }
题意:假设现在有 N 个机场,M 条航线,每天都会新增一个机场无法正常运作,每天会有 Q i对旅客从 X i机场前往 Y i机场,请计算有多少对旅客会受到影响无法完成行程。
思路:并查集+反向建图,最开始写的是dfs,只过了部分测试点,看了题解之后直呼妙啊,先把所有变量存下来,然后从后面的点开始建图,因为点是从前向后一个一个消失的,建立一个点相当于该点的前一个点消失后的状态(太妙了。在此之前还要对没有被防控的机场建图。
代码:
- #include<bits/stdc++.h>
- using namespace std;
- struct node{
- int st, ed;
- };
- int fa[50005], vis[50005];
- int n, m, d;
- vector<vector<node> > v(50005);
- vector<node> vn;
- vector<int> ans;
- stack<int> sta;
- void init(){
- for(int i = 0; i <= n; i++) fa[i] = i;
- }
- int find(int x){
- if(x == fa[x]) return x;
- else return fa[x] = find(fa[x]);
- }
- int main(){
- cin >> n >> m >> d;
- init();
- for(int i = 0; i < m; i++){
- int a, b; cin >> a >> b;
- vn.push_back({a, b});
- }
- for(int i = 0; i < d; i++){
- int c, q; cin >> c >> q;
- sta.push(c);
- vis[c] = 1;
- for(int j = 0; j < q; j++){
- int x, y; cin >> x >> y;
- v[c].push_back({x, y});
- }
- }
- for(int i = 0; i < m; i++){
- if(vis[vn[i].st] || vis[vn[i].ed]) continue;
- int finda = find(vn[i].st);
- int findb = find(vn[i].ed);
- if(finda != findb){
- fa[finda] = findb;
- }
- }
- while(!sta.empty()){
- int qf = sta.top(), cnt = 0;
- sta.pop();
- for(int i = 1; i <= n; i++) int ww = find(i);
- for(int i = 0; i < v[qf].size(); i++){
- if((fa[v[qf][i].st] != fa[v[qf][i].ed]) || vis[v[qf][i].st] || vis[v[qf][i].ed]) cnt++;
- }
- for(int i = 0; i < m; i++){
- if(vn[i].st != qf && vn[i].ed != qf) continue;
- int finda = find(vn[i].st);
- int findb = find(vn[i].ed);
- if(finda != findb){
- fa[finda] = findb;
- }
- }
- vis[qf] = 0;
- ans.insert(ans.begin(), cnt);
- }
- for(int i = 0; i < ans.size(); i++){
- printf("%d\n", ans[i]);
- }
- }
这一题没有全部过完(23/25)不知道是哪里出了问题,看好多人都是用迪杰斯特拉去路径还原,而我搜了一个弗洛伊德的路径还原板子,照着写上去了,但是没有全过。
题意:找一个点到输入的所有点耗费的能量最小,并且沿途获得的武器价值最大。
思路:典型的最短路问题,数据范围很小,考虑使用floyd,并且不仅要记录耗费的能量,还要记录获得的价值,路径能量耗费相同的情况下选择获得价值高的,还有最短路的路径还原问题。
路径还原参照博客:(36条消息) floyd——记录路径,原理详解。_小酒窝.的博客-CSDN博客_floyd算法怎么记录路径
- #include<bits/stdc++.h>
- using namespace std;
- const int inf = 0x3f3f3f3f;
- struct node{
- int me, wv; //武器价值和怪兽能量
- };
- int pre[1005][1005]; //记录路径还原
- int n, m;
- node g[1005][1005]; //记录图
- int num[1005]; //要攻破的堡垒
-
- void print(int i,int j) //路径还原的输出
- {
- if(i==j) return ;
- if(pre[i][j]==0) cout << "->" << j;
- else{
- print(i,pre[i][j]);
- print(pre[i][j],j);
- }
- }
- int main(){
- cin >> n >> m;
- memset(g, inf, sizeof(g));
- memset(pre, 0, sizeof(pre));
- for(int i = 0; i < m; i++){
- int b1, b2, x, y; cin >> b1 >> b2 >> x >> y;
- g[b1][b2] = g[b2][b1] = {x, y};
- }
- for(int k = 1; k <= n; k++){
- for(int i = 1; i <= n; i++){
- for(int j = 1; j <= n; j++){
- if(g[i][k].me + g[k][j].me < g[i][j].me)
- {
- pre[i][j]=k;
- g[i][j].me = g[i][k].me + g[k][j].me;
- g[i][j].wv = g[i][k].wv + g[k][j].wv;
- }
- else if(g[i][k].me + g[k][j].me == g[i][j].me){
- if((g[i][k].wv + g[k][j].wv > g[i][j].wv) && (g[i][k].wv + g[k][j].wv < inf ))
- {
- pre[i][j]=k;
- g[i][j].wv = g[i][k].wv + g[k][j].wv;
- }
- }
- }
- }
- }
- int k; cin>>k;
- for(int i=0;i<k;i++) cin>>num[i];
- int ans=inf;
- int ans1;
- for(int i=1;i<=n;i++)
- {
- int maxx=-1;
- for(int j=0;j<k;j++)
- {
- int dis=g[i][num[j]].me;
- maxx=max(maxx,dis);
- }
- if(ans>maxx)
- {
- ans=maxx;
- ans1=i;
- }
-
- }
- cout<<ans1<<endl;
- for(int i = 0; i < k; i++){
- printf("%d", ans1);
- print(ans1,num[i]);
- printf("\n");
- if(ans1 == num[i]) printf("0 0\n");
- else printf("%d %d\n", g[ans1][num[i]].me, g[ans1][num[i]].wv);
- }
- }
芬兰木棋(Mölkky,又称芬兰木柱)是源自芬兰的一项运动。哲哲将这个运动改造成了赛博朋克单人版,现在场上一开始有 N 根立起的小木棋(上面分别标有一个非负整数),哲哲投掷一根大木棋去击倒这些小木棋以获得分数。分数规则如下:
哲哲固定站在 (0,0) 点上,四周放着若干个小木棋 (Xi,Yi),坐标均为整数。每次哲哲可以朝一个方向扔出大木棋,大木棋会打倒这个方向上离哲哲最近的 k 个小木棋。哲哲游戏水平很高超,所以这个 k 可以自由控制。
请问哲哲最多能拿多少分,在获得最多分数的情况下最少需要扔出多少次大木棋?
规则与真实规则有较大出入,真实游玩时请以国际莫尔基组织的规则为准
输入第一行是一个正整数 N (1 ≤ N ≤ 105),表示场上一开始有 N 个木棋。
接下来 N 行,每行 3 个整数 Xi,Yi,Pi,分别表示木棋放置在 (Xi,Yi),木棋上的分数是 Pi。坐标在 32 位整数范围内,分数为小于等于 1000 的正整数。
保证 (0,0) 点没有木棋,也没有木棋重叠放置。
输出一行两个数,表示最多分数以及获得最多分数最少需要投掷大木棋多少次。
- 11
- 1 2 2
- 2 4 3
- 3 6 4
- -1 2 2
- -2 4 3
- -3 6 4
- -1 -2 1
- -2 -4 1
- -3 -6 1
- -4 -8 2
- 2 -1 999
1022 9
题意:如题,这道题题意还是比较好理解的。
思路:计算斜率,对斜率相同的点存进一个容器里,然后计算有多少个连续的1,若不是1,那就直接加上去,这里要注意的是,斜率相同,有可能象限不同,所以还要分象限,我对每个容器都加了个0,0进行隔断。
今天学到了个额外的东西,就是自定义结构体内嵌比较器一定要写清楚,清楚到足以区分每个结构体,因为有些容器的排序是完全看你的自定义结构体内嵌比较器,如果不能够区分清楚,那电脑就会认为它们是同一个东西。
- #include<bits/stdc++.h>
- #define int long long
- using namespace std;
- struct node{
- int x, y, p;
- };
- bool cmp(node a, node b){
- if(a.x != b.x) return a.x < b.x;
- else return a.y < b.y;
- }
- signed main(){
- int n, ans1 = 0, ans2 = 0; cin >> n;
- map<double, vector<node> > mp;
- for(int i = 0; i < n; i++){
- int xx, yy, pp; cin >> xx >> yy >> pp;
- ans1 += pp;
- if(mp[xx * 1.0 / yy].size() == 0){
- node a;
- a.x = 0, a.y = 0, a.p = 0;
- mp[xx * 1.0 / yy].push_back(a);
- }
- node b;
- b.x = xx, b.y = yy, b.p = pp;
- mp[xx * 1.0 / yy].push_back(b);
- }
- for(auto it = mp.begin(); it != mp.end(); it++){
- vector<node> v = (*it).second;
- sort(v.begin(), v.end(), cmp);
- int index = -1;
- for(int i = 0; i < v.size(); i++){
- if(v[i].p == 0) continue;
- else if(v[i].p != 1) ans2++;
- else{
- if(i == v.size() - 1 || v[i + 1].p != 1) ans2++;
- }
- }
- }
- printf("%lld %lld\n", ans1, ans2);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。