Guang Gong 2016 School finals

Source: Internet
Author: User

Re-fill the problem.
Problem A:krito's Crusade

Idea: Do not require a one-time kill light all the monsters inside a node. So we can use a priority queue. Take priority to kill the ones we can challenge now, and then notice that there may be more than one monster or no monster in the process room. When we kill the monsters of the X-room, we add the next layer of monsters to the queue, and if there is an empty room in the next layer of x (i.e. no monsters in the room), then take the room as a new X and continue to add the next layer of the new x until there is a room where the monsters are located.

#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{//monster int ID, DEF, add_atk;//room, defensive value, killing Extra damage};struct cmp{//by the lowest defense value and the highest additional value sorted [priority queue]bool operator () (const node &a, const node &b) {if (a.def = = b.def) {RE Turn a.add_atk < B.ADD_ATK;} return a.def > B.def;}}; BOOL Cmp0 (Node A, node B) {//By the lowest defensive value and the highest additional value ordered [preprocessing room No. 0]if (a.def = = b.def) {return a.add_atk > b.add_atk;} return A.def < B.def;} vector<node>gw[maxn]; Gw[i]: The monster situation of the first room vector<int>g[maxn]; Figure, preserving the structure of the tree int n, m, T, ATK, NUM[MAXN], vis[maxn];//points, number of monsters, sample number, monsters per room, access array bool BFs () {priority_queue<node, vector <node>, cmp>q; Monster Queue queue<int>inq; Expand the queue, save X, that is, save the room number that can extend the next level Inq.push (0); Vis[0] = 1;while (!inq.empty ()) {int top = Inq.front (); Inq.pop (); if (Gw[top].Size ())//non-empty room {for (int i = 0; i < gw[top].size (); i++) {//Add this room monster to the monster queue Q.push (Gw[top][i]);}}  else//This room is empty room {for (int i = 0; i < g[top].size (); i++) {//continue to INQ queue to join next layer node, continue to expand 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)//The current optimal can not be killed, then must not be killed in the back. {return false;} ATK + = front.add_atk;num[front.id]--;if (num[front.id] = = 0)//The monster in this room has been killed or is empty room {for (int i = 0; i < g[front.id].size () ; i++)//Ibid. {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.pu SH (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; All monster kills completed}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 ideas: Simple group backpack [in fact, the group can be greedy to beg], a total of 4 kinds of equipment, respectively, are helmets, jewelry, one-handed weapons, double kill weapons. Then we can divide the equipment into 2 groups, namely, armor and weapons. Because each set of equipment can only choose one, then it can be defined, armor Group: Only choose the helmet, only choose jewelry, helmet and jewelry combination [Note some buff bonus].    Weapon: Select only one-handed weapon, select only 2 single-handed weapons [make up two-handed weapons] and select both hands weapons. Then it is divided into 2 groups of simple 01 backpacks.    After that is the solution of the 01 knapsack. Actually can not use backpack: because only 2 groups.   Then we can under the limited gold coins, in the x= only choose the maximum attack power, in the y= only weapons to choose the maximum attack power, in the z= to choose the defense and weapon match the maximum attack. The end result is 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;//price, attack int ID, buff,//whether there is buff added to Node (in  T 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];//helmet, jewellery, one-handed weapon, two-handed weapon, Ts[1]: Armor Group, ts[2]: Weapon Group 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, &A Mp;b, &c, &d); for (int i = 0; i<a; i++)//Helmet {scanf ("%d%d", &wei, &val); Node Temp (Wei, Val, 0, 0); Tk[i] = temp; ts[1][ts++] = temp; Armor Group: Select only one helmet}for (int i = 0; i<b; i++)//jewellery {scanf ("%d%d%d%d", &wei, &val, &id, &buff); Node Temp (node (Wei, Val, Id, Buff)); Ss[i] = temp;  ts[1][ts++] = temp; Anti-Fixture group: Select only one jewelry 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; Armor Group: Helmet with buff Bonus + jewelry}for (int i = 0; i<a; i++)//Armor Set: Helmet + jewellery {for (int j = 0; j<b; j + +) {Node temp (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++)//single-handed weapons {scanf ("%d%d", &wei, &val); Node Temp (Wei, Val, 0, 0); ts[2][ts2++] = temp; Weapon Group: Select only one hand weapon dw[i] = temp;} for (int i = 0; i<c; i++)//weapon group: a one-handed weapon + one-hand weapon = two-handed weapon {for (int j = i + 1; j<c; j + +)//Because there is only one for each, so J starts with the 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++)//two-hand weapons {scanf ("%d%d", &wei, &val); Node Temp (Wei, Val, 0, 0); ts[2][ts2++] = temp; Weapon Group: Choose only one hand weapon. }//Greedy seeking method: LL ans = 0; for (int i = 0; i<ts; i++) {//Under Limited gold coins, x= only select the maximum attack damage if (TS[1][I].W <= m)///under Limited gold coins {ans = max (ans, 1LL * ts[1][i].v);} for (int i = 0; i<ts2; I+ +) {//Under Limited gold coins, y= only the weapon's maximum attack damage if (TS[2][I].W <= m)//under Limited gold coins {ans = max (ans, 1LL * ts[2][i].v);}} for (int i = 0; i<ts; i++) {//z= selection and weapon pairing maximum attack for (int j = 0; j<ts2; j + +) {if (ts[1][i].w + TS[2][J].W <= m)//In Limited Under coins {ans = max (ans, 1LL * (TS[1][I].V + ts[2][j].v));}}} printf ("%lld\n", ans); Ans=max (x, Y, z)//////////////////////////Group backpack//////////////////////////////////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's quest for a road trip: first find the shortest-circuit length, and then DFS memory search satisfies the shortest path number. We make d[i][j] the shortest short length from position (I,J) to position + corresponds to the length of the diagonal symmetry, then d[x][y] (x+y==n+1) is the actual length from (to) the end point (n,n) when the diagonal is reached. Then there is a count of the path from the diagonal along the shortest way to (the). Look at the code specifically.

#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 = + 5;const int INF = 0x3f3f3f3f;const int MOD = 1000000009;int D[MAXN][MAXN], G[MAXN][MAXN];//D: The shortest distance from the starting point to other points int n, minval, dist[4][2] = {0, 1, 0,-1, 1, 0,-1, 0};//minval: Shortest distance from start to finish, dist: direction vector stru CT 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)//is out of bounds {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) &am P;&amp D[NEXT.X][NEXT.Y] = =-1 && next.x + next.y <= n + 1) {//g[next.x][next.y] for current value, G[n-next.y + 1][n-next.x + 1] For diagonal symmetrical point values 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++)//Find shortest Path {minval = min (minval, D[i][n + 1-i]);}} int dp[maxn][maxn];int dfs (int x, int y) {if (Dp[x][y]! =-1)//Memory Search {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, NE Xty) && 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 &lt ; = N; J + +) {scanf ("%d", &g[i][j]);}} Node start; Start.x = 1; Start.y = 1, sTart.val = g[1][1] + g[n][n]; Starting point. BFS (start); The shortest distance to other points is/*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: Two binary tree in the middle sequence traversal idea: As long as two consecutive # #就输出no, otherwise output yes. Proof, only a few more can find the law

#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: Building blocks of water ideas: can be found to be able to fill the waters when and only if the shape of the U-type, you can use a stack to save a highly decreasing sequence, the current height is greater than the top height of the stack, you can fill the water.  The idea of a similar scanning line can be used for filling water. The problem also has the DP approach.

#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: I am a good man. 4 thinking: A look at Test instructions know is tolerant, but found n<=50, general tolerance is definitely tle, so consider pruning: 1, when the current recursion least common multiple already greater than 1e9 on pruning. You can see that the number of recursive layers does not exceed 10 levels [the first 10 prime numbers are multiplied by more than 1e9]. 2, the input data to optimize processing, when the n number of multiple relationships can be deleted. The output is 0 when it appears 1 o'clock.  Plus, these optimizations can be done. Though I can, I can still find a sample that makes the method tle. For example, the input 50 number, these 50 numbers are not equal to the prime number, then also tle, but the topic has a hint: the data is randomly generated, ye can be random to mess around. So unless the face is black, it is generally not the case that all the prime numbers are not equal.
#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: Current position, W: previous set of least common multiple, K: Odd Even if (W > MAXM)//pruning. {return;} for (; i < cnt; i++) {p = num[i]/gcd (Num[i], W) * W;ans + = k* (maxm/p);D FS (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)//appears 1{one = True;}} if (one) {printf ("0\n"); continue;} Sort (Temp, temp + N), for (int i = 0; i < n; i++)//delete multiple inside {for (int j = i + 1; j < N; j + +) {if (vis[i] = = 0 &&amp ; 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);p rintf ("%lld\n", Maxm-ans);}}

Problem G: I am the water question idea: is the water question. 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;}


Guang Gong 2016 School finals

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.