重现补的题目。

Problem A: Krito的讨伐

思路:不要求一次性杀光一个节点里面的所有怪物。 所以我们能够用一个优先队列。优先去杀那些我们当前能够挑战的。然后注意下处理一个房间可能有多个怪物或者无怪物。当我们杀完第x个房间的怪物时候。那么就把x的下一层的怪物增加队列,假设x的下一层出现了空房间[即房间不存在怪物],那么再把该房间当做新的x,继续增加新x的下一层直到出现了有怪物的房间位置。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<functional>
#include<cstring>
#include<string>
using namespace std;
typedef long long int LL;
const int MAXN = 1005;
struct Node
{//怪物int id, def, add_atk; //所在房间,防御值。击杀额外获得的攻击力
};
struct cmp
{//按防御值最低而且额外值最高排序[优先队列]bool operator ()(const Node &a, const Node &b){if (a.def == b.def){return a.add_atk < b.add_atk;}return a.def > b.def;}
};
bool cmp0(Node a, Node b)
{ //按防御值最低而且额外值最高排序[预处理第0号房间]if (a.def == b.def){return a.add_atk > b.add_atk;}return a.def < b.def;
}
vector<Node>GW[MAXN]; //GW[i]:第i个房间的怪物情况
vector<int>G[MAXN]; //图。保存树的结构
int n, m, t, atk, num[MAXN], vis[MAXN];
//点数。怪物数,例子数。每一个房间的怪物数。訪问数组
bool bfs()
{priority_queue<Node, vector<Node>, cmp>Q; //怪物队列queue<int>inq; //扩展队列,保存x,即保存能扩展下一层的房间号inq.push(0); vis[0] = 1;while (!inq.empty()){int top = inq.front(); inq.pop();if (GW[top].size()) //非空房间{for (int i = 0; i < GW[top].size(); i++){ //增加此房间的怪物到怪物队列Q.push(GW[top][i]);}}else //此房间为空房间{for (int i = 0; i < G[top].size(); i++){ //继续想inq队列增加下一层结点。继续扩展if (vis[G[top][i]] == 0){vis[G[top][i]] = 1;inq.push(G[top][i]);}}}}while (!Q.empty()){Node front = Q.top(); Q.pop();if (atk <= front.def) //当前最优都无法击杀。那么后面肯定击杀不了。

{ return false; } atk += front.add_atk; num[front.id]--; if (num[front.id] == 0) //此房间的怪物已经击杀完或者是空房间 { for (int i = 0; i < G[front.id].size(); i++) //同上处理 { if (vis[G[front.id][i]] == 0) { vis[G[front.id][i]] = 1; inq.push(G[front.id][i]); } } while (!inq.empty()) { int top = inq.front(); inq.pop(); if (GW[top].size()) { for (int i = 0; i < GW[top].size(); i++) { Q.push(GW[top][i]); } } else { for (int i = 0; i < G[top].size(); i++) { if (vis[G[top][i]] == 0) { vis[G[top][i]] = 1; inq.push(G[top][i]); } } } } } } return true; //所有怪物击杀完毕 } void init() { memset(num, 0, sizeof(num)); memset(vis, 0, sizeof(vis)); for (int i = 0; i <= n; i++) { G[i].clear(); GW[i].clear(); } } int main() { scanf("%d", &t); while (t--) { init(); scanf("%d%d", &n, &m); for (int i = 0; i < n - 1; i++) { int u, v; scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } scanf("%d", &atk); for (int i = 0; i < m; i++) { Node temp; scanf("%d%d%d", &temp.id, &temp.def, &temp.add_atk); GW[temp.id].push_back(temp); num[temp.id]++; } if (bfs()) { printf("Oh yes.\n"); } else { printf("Good Good Study,Day Day Up.\n"); } } return 0; }

Problem B: Sward Art Online

思路:简单分组背包[事实上分完组能够用贪心来求],一共同拥有4种装备。各自是头盔。首饰,单手武器,双杀武器。

那么我们能够把这些装备分成2组,即防具和武器。由于每组装备仅仅能选一个,那么能够这么定义,防具组:仅仅选头盔,仅仅选首饰,头盔和首饰组合[注意部分有buff加成]。 武器:仅仅选一个单手武器。 仅仅选2个单手武器[组成双手武器],仅仅选双手武器。

然后就是分成2组简单的01背包。

之后就是01背包的求解。    事实上能够不用背包:由于仅仅有2组。

那么我们能够在限有的金币下,在x=仅仅选防具的最大攻击力,在y=仅仅选武器的最大攻击力,在z=选防具和武器搭配的最大攻击力.   终于结果就是max(x,y,z)

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<set>
#include<vector>
using namespace std;
typedef long long int LL;
const int MAXN = 10000 + 5;
const int MAXZ = 105;
struct Node
{int w, v; //价格,攻击力int id, buff; //是否有buff加成Node(int b = 0, int c = 0, int d = -1, int e = 0) :w(b), v(c), id(d), buff(c){};void init(int a = 0, int b = 0, int c = -1, int d = -1){w = a; v = b; id = c; buff = d;}
};
Node Tk[MAXZ], Ss[MAXZ], Dw[MAXZ], Sw[MAXZ], TS[3][MAXN];
//头盔。首饰,单手武器,双手武器。TS[1]:防具组,TS[2]:武器组
int main()
{int t;scanf("%d", &t);while (t--){int m, a, b, c, d, ts = 0, ts2 = 0;int wei, val, Buff, Id;scanf("%d%d%d%d%d", &m, &a, &b, &c, &d);for (int i = 0; i<a; i++) //头盔{scanf("%d%d", &wei, &val);Node temp(wei, val, 0, 0);Tk[i] = temp;TS[1][ts++] = temp; //防具组:仅仅选一个头盔}for (int i = 0; i<b; i++) //首饰{scanf("%d%d%d%d", &wei, &val, &Id, &Buff);Node temp(Node(wei, val, Id, Buff));Ss[i] = temp;TS[1][ts++] = temp;  //防具组:仅仅选一个首饰if (Id == -1 || Buff <= 0){continue;}temp.init(Ss[i].w + Tk[Id].w, Ss[i].v + Tk[Id].v + Buff, 0, 0);TS[1][ts++] = temp; //防具组:有buff加成的头盔+首饰}for (int i = 0; i<a; i++) //防具组:头盔+首饰{for (int j = 0; j<b; j++){Node temp(Node(Tk[i].w + Ss[j].w, Tk[i].v + Ss[j].v, 0, 0));TS[1][ts++] = temp;}}for (int i = 0; i<c; i++) //单手武器{scanf("%d%d", &wei, &val);Node temp(wei, val, 0, 0);TS[2][ts2++] = temp; //武器组:仅仅选一个单手武器Dw[i] = temp;}for (int i = 0; i<c; i++) //武器组:一个单手武器+一个单手武器=双手武器{for (int j = i + 1; j<c; j++)//由于每种仅仅有一个,所以j要从i+1開始{Node temp(Dw[i].w + Dw[j].w, Dw[i].v + Dw[j].v);TS[2][ts2++] = temp;}}for (int i = 0; i<d; i++) //双手武器{scanf("%d%d", &wei, &val);Node temp(wei, val, 0, 0);TS[2][ts2++] = temp; //武器组:仅仅选一个双手武器。}//贪心求法:LL ans = 0; for (int i = 0; i<ts; i++){//在限有的金币下,x=仅仅选防具的最大攻击力if (TS[1][i].w <= m) //在限有的金币下{ans = max(ans, 1LL * TS[1][i].v);}}for (int i = 0; i<ts2; i++){ //在限有的金币下。y=仅仅选武器的最大攻击力if (TS[2][i].w <= m) //在限有的金币下{ans = max(ans, 1LL * TS[2][i].v);}}for (int i = 0; i<ts; i++){//z=选防具和武器搭配的最大攻击力for (int j = 0; j<ts2; j++){if (TS[1][i].w + TS[2][j].w <= m) //在限有的金币下{ans = max(ans, 1LL * (TS[1][i].v + TS[2][j].v));}}}printf("%lld\n", ans); //ans=max(x,y,z)//分组背包求法//int dp[3][MAXN];memset(dp, 0, sizeof(dp));for (int i = 1; i <= 2; i++){for (int k = 0; k <= m; k++){dp[i][k] = dp[i - 1][k];}for (int k = 0; k<(i == 1 ? ts : ts2); k++){for (int j = m; j >= TS[i][k].w; j--){dp[i][j] = max(dp[i][j], dp[i - 1][j - TS[i][k].w] + TS[i][k].v);}}}printf("%d\n", dp[2][m]);}return 0;
}

Problem C: wintermelon的魔界寻路之旅

思路:先求出最短路长度,然后dfs记忆化搜索满足最短路的路径个数。 我们令D[i][j]为从位置(1,1)到位置(i,j)的最短路长度+相应关于对角线对称的长度,那么D[X][Y](X+Y==n+1)即到达对角线的时候就是真实的从(1,1)到终点(n,n)的长度。

然后就是从对角线沿着最短路走到(1,1)的路径计数了。

详细看代码吧。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
typedef long long int LL;
const int MAXN = 100 + 5;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000009;
int D[MAXN][MAXN], g[MAXN][MAXN];
//D:起点到其它点的最短路距离
int n, minval, dist[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
//minval:起点到终点的最短路距离,dist:方向向量
struct Node
{int x, y;int val;
};
struct cmp
{bool operator()(const Node &a, const Node &b){return a.val > b.val;}
};
bool check(int x, int y)//是否越界
{return x >= 1 && x <= n&&y >= 1 && y <= n;
}
void bfs(Node start)
{priority_queue<Node, vector<Node>, cmp>Q;memset(D, -1, sizeof(D));Q.push(start);D[start.x][start.y] = start.val;while (!Q.empty()){Node t = Q.top(); Q.pop();Node next;for (int i = 0; i < 4; i++){next.x = t.x + dist[i][0];next.y = t.y + dist[i][1];if (check(next.x, next.y) && D[next.x][next.y] == -1 && next.x + next.y <= n + 1){ //g[next.x][next.y]为当前值,g[n - next.y + 1][n - next.x + 1]为对角线对称点值next.val = t.val + g[next.x][next.y] + (next.x + next.y == n + 1 ?

0 : g[n - next.y + 1][n - next.x + 1]); D[next.x][next.y] = next.val; Q.push(next); } } } minval = INF; for (int i = 1; i <= n; i++)//找到最短路 { minval = min(minval, D[i][n + 1 - i]); } } int dp[MAXN][MAXN]; int dfs(int x, int y) { if (dp[x][y] != -1)//记忆化搜索 { return dp[x][y]; } int nextx, nexty, cnt = 0; for (int i = 0; i < 4; i++) { nextx = x + dist[i][0]; nexty = y + dist[i][1]; if (check(nextx, nexty) && nextx + nexty <= n + 1 && D[nextx][nexty] + g[x][y] + (x + y == n + 1 ? 0 : g[n - y + 1][n - x + 1]) == D[x][y]) { cnt = (cnt + dfs(nextx, nexty)) % MOD; } } dp[x][y] = cnt%MOD; return dp[x][y]; } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { scanf("%d", &g[i][j]); } } Node start; start.x = 1; start.y = 1, start.val = g[1][1] + g[n][n]; //起点。 bfs(start); //求(1,1)到其它点的最短路距离 /*for (int i = 1; i <= n; i++) //Debug { for (int j = 1; j <= n; j++) { printf("%d ", D[i][j]); } printf("\n"); }*/ memset(dp, -1, sizeof(dp)); LL ans = 0; dp[1][1] = 1; for (int i = 1; i <= n; i++) { if (D[i][n + 1 - i] == minval) { ans = (ans + dfs(i, n + 1 - i)) % MOD; } } printf("%lld\n", ans); } return 0; }

Problem D: 二叉树的中序遍历

思路:仅仅要出现两个连续的##就输出no,否则就输出yes。证明略,仅仅有多画几个就能找到规律

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<set>
using namespace std;
typedef long long int LL;
const int MAXN=100000+5;
char str[MAXN];
int main()
{int t;scanf("%d",&t);while(t--){scanf("%s",str); bool flag=true;for(int i=0;i<strlen(str)-1;i++){if(str[i]=='#'&&str[i+1]=='#'){flag=false;break;}}printf(flag?"yes\n":"no\n");}return 0;
}

Problem E: 积木积水

思路:能够发现能装到水的当且仅当形状呈u型,那么能够用一个栈保存一个高度递减的序列,当前高度大于栈顶高度,则能够装水。   关于装水能够用相似扫描线的思想。  该题也有dp的做法。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
typedef long long int LL;
const int MAXN = 1000000 + 5;
struct Node
{int H;int id;
}A[MAXN];
void solve(int n)
{LL ans = 0;stack<Node>st;for (int i = 0; i < n; i++){if (st.empty()){st.push(A[i]);}else{LL top_h = 0;LL cnt = 0, tot = 0;while (!st.empty()){Node tmp = st.top();top_h = tmp.H;if (A[i].H > tmp.H){cnt += 1LL * (A[i].id - tmp.id);tot += 1LL * (A[i].id - tmp.id)*tmp.H;A[i].id = tmp.id;st.pop();}else{break;}}ans += 1LL * (cnt* min(1LL * A[i].H, top_h) - tot);st.push(A[i]);}}printf("%lld\n", ans);
}
int main()
{int t;scanf("%d", &t);while (t--){int n;scanf("%d", &n);for (int i = 0; i < n; i++){scanf("%d", &A[i].H);A[i].id = i;}solve(n);}return 0;
}

Problem F: 我是好人4

思路:一看题意就知道是容斥,可是发现n<=50,一般容斥肯定TLE无误。所以考虑剪枝:1,当当前递归时的最小公倍数已经大于1e9就剪枝。

能够发现递归层数不会超过10层[前10个质数相乘已经大于1e9了]。 2,对输入数据进行优化处理。当n个数中出现有倍数关系的则能够删掉。

出现1时就输出0。

加上这些优化就能过了。

尽管能过可是还是能找到令该方法TLE的例子。

比方输入50个数,这50个数都是互不相等的质数。那么也会TLE,可是题目有提示:数据是随机生成的,尔等尽可任意乱搞。 所以除非脸黑。一般不会遇到全是互不相等的质数的情况。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long int LL;
const int MAXM = 1e9;
LL p, ans;
int n, cnt, num[55], temp[55], vis[55];
LL gcd(LL x, LL y)
{return y ? gcd(y, x % y) : x;
}
void DFS(LL i, LL w, LL k)
{//i:当前的位置。w:之前集合的最小公倍数,k:奇偶if (w > MAXM) //剪枝。

{ return; } for (; i < cnt; i++) { p = num[i] / gcd(num[i], w) * w; ans += k*(MAXM / p); DFS(i + 1, p, -k); } } int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); cnt = 0; bool one = false; memset(vis, 0, sizeof(vis)); for (int i = 0; i < n; i++) { scanf("%d", &temp[i]); if (temp[i] == 0) { vis[temp[i]] = 1; } if (temp[i] == 1)//出现1 { one = true; } } if (one) { printf("0\n"); continue; } sort(temp, temp + n); for (int i = 0; i < n; i++) //删除里面的倍数 { for (int j = i + 1; j < n; j++) { if (vis[i] == 0 && vis[j] == 0 && temp[j] % temp[i] == 0) { vis[j] = 1; } } if (vis[i] == 0) { num[cnt++] = temp[i]; } } ans = 0; DFS(0, 1, 1); printf("%lld\n", MAXM - ans); } }

Problem G: 我是水题

思路:就是水题。2333

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<set>
using namespace std;
typedef long long int LL;
const int MAXN = 10000;
char str[MAXN];
int main()
{int t;scanf("%d", &t);getchar();while (t--){gets(str);set<char>word;for (int i = 0; i<strlen(str); i++){if (str[i] >= 'a'&&str[i] <= 'z'&&!word.count(str[i])){word.insert(str[i]);}}printf("%d\n", word.size());}return 0;
}

转载于:https://www.cnblogs.com/llguanli/p/8311741.html

广工2016校赛决赛相关推荐

  1. 2019广工ACM校赛决赛A题:思维题 HDU 6461 zsl 和hzy的生存挑战

    2019广工校赛决赛A题.HDU 6461 http://acm.hdu.edu.cn/showproblem.php?pid=6461 题目描述 zsl 和hzy 来到了臭臭城堡,打算挑战臭臭城堡的 ...

  2. 多说都是泪 GDUT 广东工业大学2016校赛决赛-网络赛 1170 Problem B Sward Art Online

    题目:点我 http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=1 今天打网络个人赛,一开始就不太顺利,到了这个题,刚看到的时候,认为是手 ...

  3. 2019 广工ACM新生赛决赛 K题(立方差公式)

    题目 https://ac.nowcoder.com/acm/contest/3036/K 思路

  4. 广东工业大学2016校赛决赛Problem B Sward Art Online(分组背包)

    Description     Krito为了打败第一层的boss - The eye of giant.SAO系统种一个人物可以装备4个物品,分别是左手武器,右手武器,首饰,盔甲,这些都可以增加一定 ...

  5. gdut校赛决赛题解

    比较水的比赛,水下博客贴个题解. Problem A: Krito的讨伐 直接模拟,把可见范围内的怪物都扔进优先队列,先杀防御低的,最后判断还有没有怪剩余就行了. #include <iostr ...

  6. 互联网+红旅赛道校赛决赛观摩部分收获

    一.小航模,大梦想--中国航空科普先行者|点燃城乡青少年科技梦想 我们感觉可以借鉴这个飞机的. 结合在线讲授与视频充分拓展科普内容,极大满足了孩子们求知欲与好奇心,给予他们自由探索新知识的空间. 让& ...

  7. 2017浙江工业大学-校赛决赛 竹之书

    Description 由于某些原因菲莉丝拿到了贤者之石,所以好像变得很厉害了 好像变得很厉害的菲莉丝想要炼成幻想乡,其中有一个原料是稗田一族对幻想乡历史的记录.现在菲莉丝拿到了一个被某只魔粘性精神体 ...

  8. 竹之书(2017浙江工业大学-校赛决赛)

    竹之书 Problem Description 由于某些原因菲莉丝拿到了贤者之石,所以好像变得很厉害了 好像变得很厉害的菲莉丝想要炼成幻想乡,其中有一个原料是稗田一族对幻想乡历史的记录.现在菲莉丝拿到 ...

  9. 2017浙江工业大学-校赛决赛 BugZhu抽抽抽!!

    Description 当前正火的一款手游阴阳师又出新式神了,BugZhu十分想要获得新出的式神,所以他决定花光所有的积蓄来抽抽抽!BugZhu经过长时间的研究后发现通过画三角外接圆能够提高获得该式神 ...

最新文章

  1. 关于tableview的优化
  2. django 连接mysql 数据库
  3. 哈希是什么?为什么哈希存取比较快?
  4. CentOS服务器iptables配置
  5. 前端学习(2197):__WEBPACK_IMPORTED_MODULE_1_vuex__.a.store is not a constructor
  6. 【软件开发底层知识修炼】十四 快速学习GDB调试一 入门使用
  7. Centos7安装图形桌面
  8. ModuleNotFoundError: No module named ‘pycocotools‘
  9. WinForm窗体生命周期
  10. 列生成(Column Generation)算法
  11. 左撇子的成长指南:我是左撇子.TXT
  12. VS2015+Qt5.8 联合配置
  13. mysql如何进行数据透视_简单谈谈MySQL数据透视表
  14. 测试硬盘怀道的软件,硬盘坏道检测工具(HDDScan)
  15. beyond compare怎么设置不比较文件修改时间?
  16. onlyOffice常用api整理(1)
  17. office 2016错误代码30175-13(30) win10
  18. 【c++】保留两位小数
  19. 小姐姐太强了,动图展示 10 大 Git 命令,不会都难
  20. 重新回到Fcitx5的怀抱

热门文章

  1. 女生不适合学java?其实不然,女生往往更有优势!
  2. Openlayers的空间查询wfs
  3. 前端html转换PDF,指定html转换成pdf
  4. Android文件下载——单线程断点下载
  5. 2021年压力管道巡检维护最新解析及压力管道巡检维护模拟考试题库
  6. html中改变字的间距,网页改变字行间距操作方法
  7. AMBA-AXI(一)burst 传输-INCR/WRAP/Fixed
  8. 中国科学技术大学2020计算机拟录取,中国科学技术大学2021年硕士研究生拟录取名单...
  9. 集群对讲 文字 文件_英国小学生是如何学习中国高考词汇的?第一讲(文末留言送礼)...
  10. 云应用的概念、特性及部署