目录
- 1071 Speech Patterns (25分) 推荐:1星
- 1072 Gas Station (30分) 推荐:3星
- 1073 Scientific Notation (20分) 推荐:1星
- 1074 Reversing Linked List (25分) 推荐:1星
- 1075 PAT Judge (25分)
- 1076 Forwards on Weibo (30分) 推荐:2星
- 1077 Kuchiguse (20分)
- 1078 Hashing (25分) 推荐:1星
- 1079 Total Sales of Supply Chain (25分) 推荐:经典
- 1080 Graduate Admission (30分)
1071 Speech Patterns (25分) 推荐:1星
题目
Sample Input:
Can1: "Can a can can a can? It can!"
Sample Output:
can 5
分析
推荐:1星
打表,字符串处理
要点
- isalnum :是数字且是字母
- 获取子树 s.substr(i, length)
- tolower转换小写
题解
找到字符串中的最大重复次数
#include <iostream>
#include <map>
#include <cctype>
using namespace std;
int main(){
string s, t; ///t是临时字符
getline(cin ,s);
map<string, int> m;
for(int i = 0 ; i < s.length(); i++){
if (isalnum(s[i])){
s[i] = tolower(s[i]); ///都是小写
t += s[i];
}
if (!isalnum(s[i]) || i == s.length() - 1){
if(t.length() != 0) m[t]++; ///统计该字符串的数量
t = "";
}
}
int maxn = 0;
for(auto it = m.begin(); it != m.end(); it++){
if(it->second > maxn){
t = it->first;
maxn = it->second;
}
}
cout << t << " " << maxn;
return 0;
}
1072 Gas Station (30分) 推荐:3星
题目
Sample Input 1:
4 3 11 5
1 2 2
1 4 2
1 G1 4
1 G2 3
2 3 2
2 G2 1
3 4 2
3 G3 2
4 G1 3
G2 G1 1
G3 G2 2
Sample Output 1:
G1
2.0 3.3
Sample Input 2:
2 1 2 10
1 G1 9
2 G1 20
Sample Output 2:
No Solution
分析
推荐:3星
来吧,再多熟悉Dijskra。
现在这种有变化的Dijskra会考得多一点。
要点
- 在dij上又加入了一些变化
- 在dij最外面再套一层循环,只遍历gas station的点
题解
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int inf = 999999999; ///无效初始值
int n, m, k, ds, station;
int e[1020][1020], dis[1020]; ///边权, 距离
bool visit[1020]; ///是否拜访过
int main() {
fill(e[0], e[0] + 1020 * 1020, inf); ///初始化边权
fill(dis, dis + 1020, inf); ///初始化距离
scanf("%d%d%d%d", &n, &m, &k, &ds);
for(int i = 0; i < k; i++) {
int tempdis;
string s, t;
cin >> s >> t >> tempdis;
int a, b;
if(s[0] == 'G') {
s = s.substr(1); ///提取字符串
a = n + stoi(s); ///G点
} else {
a = stoi(s); /// 直接转换
}
if(t[0] == 'G') { ///同上
t = t.substr(1);
b = n + stoi(t);
} else {
b = stoi(t);
}
e[a][b] = e[b][a] = tempdis; ///边权确认值
}
int ansid = -1;
double ansdis = -1, ansaver = inf;
for(int index = n + 1; index <= n + m; index++) { ///G点开始
double mindis = inf, aver = 0; ///mindis :当前最短距离, aver 平均距离
fill(dis, dis + 1020, inf); ///重新初始化边权
fill(visit, visit + 1020, false); ///重新初始化记录数组
dis[index] = 0; ///当前点距离置0
for(int i = 0; i < n + m; i++) {
int u = -1, minn = inf;
for(int j = 1; j <= n + m; j++) { ///找到最短距离
if(visit[j] == false && dis[j] < minn) {
u = j;
minn = dis[j];
}
}
if(u == -1) break;
visit[u] = true;
for(int v = 1; v <= n + m; v++) {
if(visit[v] == false && dis[v] > dis[u] + e[u][v])
dis[v] = dis[u] + e[u][v];
}
}
for(int i = 1; i <= n; i++) {
if(dis[i] > ds) {
mindis = -1;
break;
}
if(dis[i] < mindis) mindis = dis[i];
aver += 1.0 * dis[i];
}
if(mindis == -1) continue;
aver = aver / n;
if(mindis > ansdis) {
ansid = index;
ansdis = mindis;
ansaver = aver;
} else if(mindis == ansdis && aver < ansaver) {
ansid = index;
ansaver = aver;
}
}
if(ansid == -1)
printf("No Solution");
else
printf("G%d\n%.1f %.1f", ansid - n, ansdis, ansaver);
return 0;
}
1073 Scientific Notation (20分) 推荐:1星
题目
Sample Input 1:
+1.23400E-03
Sample Output 1:
0.00123400
Sample Input 2:
-1.2E+10
Sample Output 2:
-12000000000
分析
推荐:1星
通过找下标也做到,但是代码和思维比较难
要点
- 找某个值,用while要比for来得直观
题解
#include <iostream>
using namespace std;
int main() {
string s;
cin >> s;
int i = 0;
while (s[i] != 'E') i++;
string t = s.substr(1, i-1);
int n = stoi(s.substr(i+1));
if (s[0] == '-') cout << "-";
if (n < 0) { ///n是e的值
cout << "0.";
for (int j = 0; j < abs(n) - 1; j++) cout << '0';
for (int j = 0; j < t.length(); j++)
if (t[j] != '.') cout << t[j];
} else {
cout << t[0];
int cnt, j;
///j=2跳过了.点, 然后由e的个数,决定遍历的长度
for (j = 2, cnt = 0; j < t.length() && cnt < n; j++, cnt++) cout << t[j];
if (j == t.length()) { ///如果j已经到结尾
for (int k = 0; k < n - cnt; k++) cout << '0';
} else { ///如果没有则输出.,然后将余下的输入完成
cout << '.';
for (int k = j; k < t.length(); k++) cout << t[k];
}
}
return 0;
}
1074 Reversing Linked List (25分) 推荐:1星
题目
Sample Input:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
分析
推荐:1星
链表数组,还可以用vector来解决
对链表数据进行排序,或者翻转得到结果。划重点:链表可排序,大家可以思考下,用排序的方法怎么解决这道题。
要点
- i / k * k + k - 1 - i % k 要分两部分看,第一部分: i/k*k 对取nk整数, 第二部分:k-1-i%k倒序
题解
通过下标
#include <iostream>
using namespace std;
int main() {
int first, k, n, sum = 0;
cin >> first >> n >> k;
int temp, data[100005], next[100005], list[100005], result[100005];
for (int i = 0; i < n; i++) {
cin >> temp;
cin >> data[temp] >> next[temp];
}
while (first != -1) {
list[sum++] = first;
first = next[first];
}
for (int i = 0; i < sum; i++) result[i] = list[i];
for (int i = 0; i < (sum - sum % k); i++)
result[i] = list[i / k * k + k - 1 - i % k]; ///翻转复制
for (int i = 0; i < sum - 1; i++)
printf("%05d %d %05d\n", result[i], data[result[i]], result[i + 1]);///i/k*k 对取nk整数,k-1-i%k倒序
printf("%05d %d -1", result[sum - 1], data[result[sum - 1]]);
return 0;
}
1075 PAT Judge (25分)
题目
Sample Input:
7 4 20
20 25 25 30
00002 2 12
00007 4 17
00005 1 19
00007 2 25
00005 1 20
00002 2 2
00005 1 15
00001 1 18
00004 3 25
00002 2 25
00005 3 22
00006 4 -1
00001 2 18
00002 1 20
00004 1 15
00002 4 18
00001 3 4
00001 4 2
00005 2 -1
00004 2 0
Sample Output:
1 00002 63 20 25 - 18
2 00005 42 20 0 22 -
2 00007 42 - 25 - 17
2 00001 42 18 18 4 2
5 00004 40 15 0 25 -
题解
模拟题
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct node {
int rank, id, total = 0;
vector<int> score;
int passnum = 0;
bool isshown = false;
};
bool cmp1(node a, node b) {
if(a.total != b.total)
return a.total > b.total;
else if(a.passnum != b.passnum)
return a.passnum > b.passnum;
else
return a.id < b.id;
}
int main() {
int n, k, m, id, num, score;
scanf("%d %d %d", &n, &k, &m);
vector<node> v(n + 1);
for(int i = 1; i <= n; i++)
v[i].score.resize(k + 1, -1);
vector<int> full(k + 1);
for(int i = 1; i <= k; i++)
scanf("%d", &full[i]);
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &id, &num, &score);
v[id].id = id;
v[id].score[num] = max(v[id].score[num], score);
if(score != -1)
v[id].isshown = true;
else if(v[id].score[num] == -1)
v[id].score[num] = -2;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= k; j++) {
if(v[i].score[j] != -1 && v[i].score[j] != -2)
v[i].total += v[i].score[j];
if(v[i].score[j] == full[j])
v[i].passnum++;
}
}
sort(v.begin() + 1, v.end(), cmp1);
for(int i = 1; i <= n; i++) {
v[i].rank = i;
if(i != 1 && v[i].total == v[i - 1].total)
v[i].rank = v[i - 1].rank;
}
for(int i = 1; i <= n; i++) {
if(v[i].isshown == true) {
printf("%d %05d %d", v[i].rank, v[i].id, v[i].total);
for(int j = 1; j <= k; j++) {
if(v[i].score[j] != -1 && v[i].score[j] != -2)
printf(" %d", v[i].score[j]);
else if(v[i].score[j] == -1)
printf(" -");
else
printf(" 0");
}
printf("\n");
}
}
return 0;
}
1076 Forwards on Weibo (30分) 推荐:2星
题目
Sample Input:
7 3
3 2 3 4
0
2 5 6
2 3 1
2 3 4
1 4
1 5
2 2 6
Sample Output:
4
5
分析
推荐:2星
BFS,广度搜索的题目,用深度搜索也可以,但是要处理细节很多。
所以这道题使用广度搜索要比深度搜索好。
题解
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
int n, l, m, k;
struct node {
int id, layer;
};
vector<vector<int>> v;
int bfs(node tnode) { ///¹ã¶ÈËÑË÷
bool inq[1010] = {false};
queue<node> q;
q.push(tnode);
inq[tnode.id] = true;
int cnt = 0;
while(!q.empty()) {
node top = q.front();
q.pop();
int topid = top.id;
for(int i = 0; i < v[topid].size(); i++) {
int nextid = v[topid][i];
if(inq[nextid] == false && top.layer < l) {
node next = {nextid, top.layer + 1};
q.push(next);
inq[next.id] = true;
cnt++;
}
}
}
return cnt;
}
int main() {
scanf("%d %d", &n, &l);
v.resize(n + 1);
for(int i = 1; i <= n; i++) {
scanf("%d", &m);
for(int j = 0; j < m; j++) {
int temp;
scanf("%d", &temp);
v[temp].push_back(i);
}
}
scanf("%d", &k);
int tid;
for(int i = 0; i < k; i++) {
scanf("%d", &tid);
node tnode = {tid, 0};
printf("%d\n", bfs(tnode));
}
return 0;
}
1077 Kuchiguse (20分)
题目
Sample Input 1:
3
Itai nyan~
Ninjin wa iyadanyan~
uhhh nyan~
Sample Output 1:
nyan~
Sample Input 2:
3
Itai!
Ninjinnwaiyada T_T
T_T
Sample Output 2:
nai
要点
- scanf("%d\n", &n); 注意这个\n 换行符,如果不加,在getline的时候就会获取到错误的数据。
- substr可以等于len,但是不能小于0
题解
找结尾口头禅
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
scanf("%d\n", &n);
string ans;
for(int i = 0; i < n; i++) {
string s;
getline(cin, s); ///直接读取1整行
int lens = s.length();
reverse(s.begin(), s.end()); ///反转字符串
if(i == 0) {
ans = s; /// 第一个则采取完数据后与下一个进行对比
continue;
} else {
int lenans = ans.length();
if(lens < lenans) swap(ans, s); ///字符串内容交换
int minlen = min(lens, lenans);
for(int j = 0; j < minlen; j++) {
if(ans[j] != s[j]) {
ans = ans.substr(0, j);
break;
}
}
}
}
reverse(ans.begin(), ans.end());
if (ans.length() == 0) ans = "nai";
cout << ans;
return 0;
}
代码再简洁一点
#include <iostream>
#include <string>
using namespace std;
int main(){
#ifndef ONLINE_JUDGE
freopen("data.txt", "r",stdin);
#endif // ONLINE_JUDGE
int n;
string s, t;
scanf("%d\n", &n);
getline(cin, s);
for(int i = 1; i < n; i++){
getline(cin, t);
int j = 0, len = min(s.size(), t.size());
while(s[s.length()-1-j] == t[t.length()-1-j] && j < len) j++;
if (j==0) s="";
else s = s.substr(s.length()-j);
}
if (s.size() == 0) printf("nai");
else cout << s;
return 0;
}
1078 Hashing (25分) 推荐:1星
题目
Sample Input:
4 4
10 6 4 15
Sample Output:
0 1 4 -
分析
推荐:1星
hash问题
要点
- 平方探测:Quadratic probing , 是i*i, 不是2n
题解
#include <iostream>
using namespace std;
int size, n, hashTable[10100];
bool isprime(int num) { ///素数判断
if(num == 1) return false;
for(int i = 2; i * i <= num; i++)
if(num % i == 0) return false;
return true;
}
void insert(int key) { ///hash找空位
for(int step = 0; step < size; step++) {
int index = (key + step * step) % size;
if(hashTable[index] == 0) {
hashTable[index] = 1;
cout << index % size;
return ;
}
}
cout << '-';
}
int main() {
cin >> size >> n;
while(!isprime(size)) size++; ///不是素数则尺寸加1
for(int i = 0; i < n; i++) {
int key;
cin >> key;
if(i != 0) cout << ' ';
insert(key);
}
return 0;
}
1079 Total Sales of Supply Chain (25分) 推荐:经典
题目
Sample Input:
10 1.80 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3
Sample Output:
42.4
分析
dfs,推荐:经典,而且经销商这种题型也是常考的。
题解
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
struct node {
double data;
vector<int> child;
};
vector<node> v;
double ans = 0.0, p, r;
void dfs(int index, int depth) {
if(v[index].child.size() == 0) {
ans += v[index].data * pow(1 + r, depth);
return ;
}
for(int i = 0; i < v[index].child.size(); i++)
dfs(v[index].child[i], depth + 1);
}
int main() {
int n, k, c;
scanf("%d %lf %lf", &n, &p, &r);
r = r / 100;
v.resize(n);
for(int i = 0; i < n; i++) {
scanf("%d", &k);
if(k == 0) {
scanf("%lf", &v[i].data);
} else {
for(int j = 0; j < k; j++) {
scanf("%d", &c);
v[i].child.push_back(c);
}
}
}
dfs(0, 0);
printf("%.1f", ans * p);
return 0;
}
1080 Graduate Admission (30分)
题目
Sample Input:
11 6 3
2 1 2 2 2 3
100 100 0 1 2
60 60 2 3 5
100 90 0 3 4
90 100 1 2 0
90 90 5 1 3
80 90 1 0 2
80 80 0 1 2
80 80 0 1 2
80 70 1 3 2
70 80 1 2 3
100 100 0 2 4
Sample Output:
0 10
3
5 6 7
2 8
1 4
分析
模拟题
题解
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct peo{
int id, ge, gi, fin;
vector<int> choice;
};
bool cmp(peo& a, peo& b) {
if (a.fin != b.fin) return a.fin > b.fin;
return a.ge > b.ge;
}
bool cmp2(peo& a, peo& b) {
return a.id < b.id;
}
int main(){
int n, m, k, quota[110], cnt[110] = {0};
scanf("%d%d%d", &n, &m, &k);
vector<peo> stu(n), sch[110];
for(int i = 0; i < m; i++)
scanf("%d","a[i]);
for(int i = 0; i < n; i++) {
scanf("%d%d", &stu[i].ge, &stu[i].gi);
stu[i].id = i;
stu[i].fin = stu[i].ge + stu[i].gi;
stu[i].choice.resize(k);
for(int j = 0; j < k; j++)
scanf("%d", &stu[i].choice[j]);
}
sort(stu.begin(), stu.end(), cmp);
for(int i = 0; i < n; i++) {
for(int j = 0; j < k; j++) {
int schid = stu[i].choice[j];
int lastindex = cnt[schid] - 1;
if(cnt[schid] < quota[schid] || (stu[i].fin == sch[schid][lastindex].fin) && stu[i].ge == sch[schid][lastindex].ge) {
sch[schid].push_back(stu[i]);
cnt[schid]++;
break;
}
}
}
for(int i = 0; i < m; i++) {
sort(sch[i].begin(), sch[i].end(), cmp2);
for(int j = 0; j < cnt[i]; j++) {
if(j != 0) printf(" ");
printf("%d", sch[i][j].id);
}
printf("\n");
}
return 0;
}