A.Toy Cars
题意:给出n辆玩具车两两碰撞的结果,找出没有翻车过的玩具车。
思路:简单题。遍历即可。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int mp[110][110]; 5 int goodcar[110]; 6 int main() 7 { 8 int n; 9 scanf("%d", &n); 10 for (int i = 1; i <= n; i++) 11 { 12 for (int j = 1; j <= n; j++) scanf("%d", *(mp + i) + j); 13 } 14 int cnt = 0; 15 for (int i = 1; i <= n; i++) 16 { 17 bool ok = true; 18 for (int j = 1; j <= n; j++) 19 { 20 if (j == i) continue; 21 if (mp[i][j] == 1 || mp[i][j] == 3||mp[j][i]==2||mp[j][i]==3) 22 { 23 ok = false; 24 break; 25 } 26 } 27 if (ok) goodcar[cnt++] = i; 28 } 29 printf("%d ", cnt); 30 if (cnt) 31 { 32 for (int i = 0; i < cnt; i++) 33 { 34 if (i) printf(" "); 35 printf("%d", goodcar[i]); 36 } 37 printf(" "); 38 } 39 return 0; 40 }
B. Equidistant String
题意:给出两个相同长度的字符串,求是否存在一个字符串使得其与给出的两个字符串的在同一位置不同字符的个数相同。
思路:如果原本两个字符串之间不同的字符为偶数,则存在。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 char s[100010]; 6 char t[100010]; 7 int main() 8 { 9 scanf("%s%s", s, t); 10 int len = strlen(s); 11 int diff = 0; 12 for (int i = 0; i < len; i++) if (s[i] != t[i]) diff++; 13 if (diff % 2) printf("impossible "); 14 else 15 { 16 int cnt = 0; 17 for (int i = 0; i < len; i++) 18 { 19 if (s[i] == t[i]) printf("%c", s[i]); 20 else 21 { 22 if (cnt < diff / 2) printf("%c", s[i]); 23 else printf("%c", t[i]); 24 cnt++; 25 } 26 } 27 } 28 29 30 return 0; 31 }
C. Woodcutters
题意:一条路上有n棵树,给出其坐标和高度。现在有一个伐木工从1开始向右伐木,每遇见一棵树选择伐或者不伐,但必须遵守以下规则:假如其坐标为xi,高度为hi,那么如果伐木并让它向左倒,则其会占据[xi-hi,xi]的长度;如果向右倒,则会占据[xi,xi+hi]的长度,否则不砍的话只会占据xi这个位置。并且如果砍伐后其倒下所占据的地方不能被其他树占据。问最多能砍多少树?
思路:
1)贪心+模拟。
①第一棵直接向左倒。
②非第一棵树,记为cur,如果能够向前倒标记为true,且x则直接砍.
③当前cur不符合②时,如果向后倒同时下一棵树也能向前倒,且间距能容纳,则都砍,cur=cur+2,并设置向前倒标记为true,回到②,否则到④;
④如果cur能向后倒,cur+1能向前倒,但是间距只能容纳一棵树,我们需要枚举t=cur+2,判断t-1与t能否砍,直至cur==n或者t-1、t两棵树之间的间距至少比其中一棵树小或者t-1、t都能被间距容纳。如果为第一种情况,则cur~n-1的树都能砍;第二种情况,如果只比其中一棵树小,cur~t中只能砍t-cur棵,并且如果第t棵能够向前倒,则选择砍第t棵,而非t-1棵,重设向前倒标记,否则比最后两棵树都小,则只能砍t-cur-1棵;第三种情况,则都砍,cur=t+1,并设置向前倒标记为true,回到②;
⑤如果cur=n-1,则直接砍。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int px[100010]; 6 int ph[100010]; 7 int main() 8 { 9 int n; 10 scanf("%d", &n); 11 for (int i = 0; i < n; i++) scanf("%d%d", px + i, ph + i); 12 int cnt = 0; 13 bool canfront = true; 14 for (int i = 0; i < n; i++) 15 { 16 if (i == 0||i==n-1) cnt++; 17 else if (i < n - 1) 18 { 19 if (canfront) 20 { 21 if (px[i] - ph[i] > px[i - 1]) 22 { 23 cnt++; 24 continue; 25 } 26 } 27 if (px[i] + ph[i] < px[i + 1]) 28 { 29 if (px[i + 1] - ph[i + 1] > px[i]) 30 { 31 if (px[i + 1] - ph[i + 1] > px[i] + ph[i]) cnt += 2, i++, canfront = true; 32 else 33 { 34 int t = i + 2; 35 while (t < n&&px[t - 1] + ph[t - 1]<px[t] && px[t] - ph[t]>px[t - 1] && px[t - 1] + ph[t - 1] >= px[t] - ph[t]) t++; 36 if (t == n) cnt += n - i, i = n, canfront = true; 37 else if (px[t - 1] + ph[t - 1] < px[t] - ph[t]) cnt += t - i + 1, i = t, canfront = true; 38 else if (px[t - 1] + ph[t - 1] < px[t])cnt += t - i, i = t-1, canfront = false; 39 else if (px[t] - ph[t] > px[t - 1]) cnt += t - i, i = t, canfront = true; 40 else cnt += t - i - 1, i = t - 1, canfront = false; 41 } 42 } 43 else cnt += 1,canfront=false; 44 } 45 else canfront = true; 46 } 47 } 48 printf("%d ", cnt); 49 50 return 0; 51 }
2)另一种贪心+模拟
①第一棵向左倒,最后一棵向右倒
②其余的树,如果能够向前倒,则+1;否则如果能向后倒,+1并且更新xi=xi+hi.
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int px[100010]; 6 int ph[100010]; 7 int main() 8 { 9 int n; 10 scanf("%d", &n); 11 for (int i = 0; i < n; i++) scanf("%d%d", px + i, ph + i); 12 int cnt = 0; 13 bool canfront = true; 14 for (int i = 0; i < n; i++) 15 { 16 if (i == 0||i==n-1) cnt++; 17 else if (i < n - 1) 18 { 19 if (px[i] - ph[i] > px[i - 1]) cnt++; 20 else 21 { 22 if (px[i] + ph[i] < px[i + 1]) cnt++, px[i] += ph[i]; 23 } 24 } 25 } 26 printf("%d ", cnt); 27 return 0; 28 }
D. Queue
题意:有一队人在排队,如果轮到他时其等待时间(为其前面所有人的服务时间之和)不大于其需要的服务时间,则其会感到满意。现在你可以随意调动人的位置,求满意的人的最大数目。
思路:先从小到大排序,然后从第一个枚举,符合条件则+1,等待时间+ti,否则不管他。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int t[100010]; 6 int main() 7 { 8 int n; 9 scanf("%d", &n); 10 for (int i = 0; i < n; i++) 11 { 12 scanf("%d", t + i); 13 } 14 sort(t, t + n); 15 long long tot = 0; 16 int cnt = 0; 17 for (int i = 0; i < n; i++) 18 { 19 if (t[i] >= tot) cnt++, tot += t[i]; 20 } 21 printf("%d ", cnt); 22 23 return 0; 24 }
E. Paths and Trees
题意:有一个无向带权图,给出顶点,求一棵以该顶点为根的树,其每条边之和最小。
思路:SPFA变形,更新到该点的距离和连接该点的边。
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 const int maxn = 300010; 8 const int maxm = 300010; 9 struct edge 10 { 11 int id, to,cost,next; 12 edge(int ii=0,int tt=0,int cc=0,int nn=0):id(ii),to(tt),cost(cc),next(nn){} 13 }; 14 int Head[maxn], totedge; 15 edge Edge[maxm * 2]; 16 void addedge(int id,int from, int to, int w) 17 { 18 Edge[totedge] = edge(id, to, w, Head[from]); 19 Head[from] = totedge++; 20 Edge[totedge] = edge(id, from, w, Head[to]); 21 Head[to] = totedge++; 22 } 23 long long dis[maxn]; 24 int pre[maxn]; 25 bool vis[maxn]; 26 const long long INF =0x3f3f3f3f3f3f3f3f; 27 void SPFA(int st) 28 { 29 queue<int>q; 30 q.push(st); 31 vis[st] = true; 32 memset(dis, INF, sizeof(dis)); 33 memset(pre, -1, sizeof(pre)); 34 dis[st] = 0; 35 while (!q.empty()) 36 { 37 int u = q.front(); 38 q.pop(); 39 vis[u] = false; 40 for (int i = Head[u]; i != -1; i = Edge[i].next) 41 { 42 int v = Edge[i].to; 43 if (dis[v] > dis[u] + Edge[i].cost) 44 { 45 dis[v] = dis[u] + Edge[i].cost; 46 pre[v] = i; 47 if (!vis[v]) 48 { 49 vis[v] = true; 50 q.push(v); 51 } 52 } 53 else if (dis[v] == dis[u] + Edge[i].cost) 54 { 55 if (Edge[pre[v]].cost > Edge[i].cost) 56 { 57 pre[v]=i; 58 } 59 } 60 } 61 } 62 } 63 int main() 64 { 65 int n, m; 66 scanf("%d%d", &n, &m); 67 memset(Head, -1, sizeof(Head)); 68 totedge = 0; 69 for (int i = 1; i <= m; i++) 70 { 71 int u, v, c; 72 scanf("%d%d%d", &u, &v, &c); 73 addedge(i, u, v, c); 74 } 75 int start; 76 scanf("%d", &start); 77 SPFA(start); 78 long long tot = 0; 79 for (int i=1;i<=n; i++) 80 { 81 if (i == start) continue; 82 tot += 1ll * Edge[pre[i]].cost; 83 } 84 printf("%I64d ", tot); 85 bool first = true; 86 for (int i=1; i<=n; i++) 87 { 88 if (i == start) continue; 89 if (first) printf("%d", Edge[pre[i]].id), first = false; 90 else printf(" %d", Edge[pre[i]].id); 91 } 92 printf(" "); 93 return 0; 94 }