Educational Codeforces Round 40 (Rated for Div. 2)
A. Diagonal Walking
简单模拟
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; int n; char s[110]; vector<char> G; int main(){ scanf("%d", &n); scanf("%s", s+1); int i = 1; while(i<=n){ if((s[i] == 'U' && s[i+1] == 'R') || (s[i] == 'R' && s[i+1] == 'U')){ G.push_back('D'); i+=2; } else{ G.push_back(s[i]); i++; } } printf("%d\n", G.size()); return 0; }
B. String Typing(kmp)
题意:有两种操作,往一个字符串末尾添加一个字符,可以操作无限次;将当前字符复制一遍,最多操作一次。现给出一个字符串,问最少操作多少步能够得到该字符串。
题解:首先求出next数组和最小循环节,从后往前找,若某一个前缀出现了多k次该循环节,那么最优的做法一定是先单个添加k/2个循环节,然后复制一遍,然后剩下的再单个添加。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; int n; char s[220]; int nxt[220]; void getnxt(){ nxt[0] = -1; int i = 0, j = -1; while(i<n){ if(j == -1 || s[i] == s[j]){ i++; j++; nxt[i] = j; } else{ j = nxt[j]; } } } int main(){ scanf("%d", &n); scanf("%s", s); getnxt(); int len = 0; int ans = 0; int k = 0; for(int i = n; i>=0; i--){ int t = i-nxt[i]; if(i%t == 0 && i/t>1){ len = t; k = i/t; break; } } if(len!=0){ ans+=len*(k/2); ans++; ans+=len*(k-2*(k/2)); ans+=n-len*k; } else{ ans = n; } printf("%d\n", ans); return 0; }
D. Fight Against Traffic
题意:给一张图,有一个起点s和终点t,能加一条边,使得s到t的最短路径不减小, 求方案数。
题意:可以从s和t各跑一遍最短路,因为点只有1000然后枚举任意两点之间连边是否使得最短路减小。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; struct di{ int u, d; bool operator < (const di &a) const{ return d>a.d; } }; priority_queue<di> que; struct Edge{ int v, w, next; }edge[2000010]; int head[1010], cnt; int dis[2][1010]; bool vis[1010]; int ma[1010][1010]; int n, m, s, t; void init(){ memset(head, -1, sizeof(head)); cnt = 0; } void add(int u, int v, int w){ edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; } void dijkstra(int k, int st){ memset(vis, false, sizeof(vis)); for(int i = 1; i<=n; i++){ dis[k][i] = 0x3f3f3f3f; } di e; e.u = st; e.d = 0; dis[k][st] = 0; que.push(e); while(!que.empty()){ e = que.top(); que.pop(); int u = e.u; if(vis[u] == true) continue; vis[u] = true; for(int i = head[u]; i!=-1; i = edge[i].next){ int v = edge[i].v, w = edge[i].w; if(dis[k][v]>dis[k][u]+w){ dis[k][v] = dis[k][u]+w; e.u = v; e.d = dis[k][v]; que.push(e); } } } } int main(){ scanf("%d %d %d %d", &n, &m, &s, &t); init(); for(int i = 1; i<=m; i++){ int u, v; scanf("%d %d", &u, &v); add(u, v, 1); add(v, u, 1); ma[u][v] = ma[v][u] = 1; } dijkstra(0, s); dijkstra(1, t); int ans = 0; for(int i = 1; i<=n; i++){ for(int j = i+1; j<=n; j++){ if(ma[i][j] || i == j) continue; if(dis[0][i]+1+dis[1][j]<dis[0][t]) continue; if(dis[0][j]+1+dis[1][i]<dis[0][t]) continue; ans++; } } printf("%d\n", ans); return 0; }