一、 Arithmetic Progression of Primes (20 分)
分析:输入n和maxp,找出maxp范围内n个间隔最大的素数。上来就是挺麻烦的一道题,想了好多种方法,最后还是暴力解体,将所有素数放到了一个数组里面,从后往前遍历,间隔逐渐减小。套了三层循环,所以有一测试点超时了,不知道怎么改,扣了三分。
#include<bits/stdc++.h>
using namespace std;
set<int> s;
vector<int> num(100050, 0), v;
bool prime(int x){
num[2] = 1;
s.insert(2);
for(int i=2; i<=x; i++){
int flag = 0;
for(int j=2; j<=sqrt(i)+1; j++){
if(i % j == 0){
flag = 1;
}
}
if(flag == 0){
num[i] = 1;
s.insert(i);
}
}
for(auto it=s.begin(); it!=s.end(); it++){
v.push_back(*it);
}
}
int main(){
int n, maxp;
scanf("%d %d", &n, &maxp);
prime(maxp);
int cnt = -1;
int dis = -1;
if(n != 1){
dis = maxp/(n-1);
while(1){
int flag1 = 0;
if(dis == 0){
break;
}
for(int i=v.size()-1; i>=0; i--){
int flag = 0;
for(int j=0; j<n; j++){
if(find(v.begin(), v.end(), v[i] - dis*j) == v.end()){
flag = 1;
}
}
if(flag == 0){
cnt = v[i];
flag1 = 1;
break;
}
}
if(flag1 == 1){
break;
}
dis--;
}
}
if(cnt != -1){
for(int i=n-1; i>=0; i--){
if(i != n-1) printf(" ");
printf("%d", cnt - dis*i);
}
}else{
int maxi = -1;
for(auto it=s.begin(); it!=s.end(); it++){
maxi = max(*it, maxi);
}
printf("%d", maxi);
}
return 0;
}
二、Lab Access Scheduling (25 分)
分析:输入n,n行开始时间与结束时间,找出在一天内最多能安排几个节目。唯一的一道水题,使用贪心算法,按结束时间来排序,每次取起始时间比上一个结束时间大的。
#include<bits/stdc++.h>
using namespace std;
struct requ{
int start, end;
};
requ r[2050];
bool cmp(requ a, requ b){
return a.end < b.end;
}
int main(){
int n, sh, sm, ss, eh, em, es;
cin >> n;
for(int i=0; i<n; i++){
scanf("%d:%d:%d", &sh, &sm, &ss);
scanf("%d:%d:%d", &eh, &em, &es);
r[i].start = sh*3600 + sm*60 + ss;
r[i].end = eh*3600 + em*60 + es;
}
sort(r, r+n, cmp);
int mstart = r[0].start, mend = r[0].end, sum = 1;
for(int i=1; i<n; i++){
if(r[i].start >= mend){
sum++;
mend = r[i].end;
}
}
cout << sum;
return 0;
}
三、Structure of Max-Heap (25 分)
分析:输入n个数,将其构成大根堆,再输入m行,每行有一个判断句,正确就输出1,否则0。这道题的输入是真的麻烦,题目倒是不难,无非就是拿到数后去判断是否正确。但有一个测试点错了,不知道错在哪,扣了4分。
#include<bits/stdc++.h>
using namespace std;
int heap[1050];
int len = 1;
void Insert(int k){
heap[len++] = k;
int cnt = len-1;
while(cnt != 1 && cnt != 0){
if(heap[cnt] > heap[cnt/2]){
int temp = heap[cnt];
heap[cnt] = heap[cnt/2];
heap[cnt/2] = temp;
cnt = cnt/2;
}else{
break;
}
}
}
int main(){
int n, m, k;
cin >> n >> m;
for(int i=0; i<n; i++){
cin >> k;
Insert(k);
}
string my = "";
for(int i=0; i<m; i++){
int x, xi = 0;
string s;
scanf("%d", &x);
getline(cin, s);
if(s[1] == 'i'){
if(s[9] == 'a'){//parent
string res = "";
for(int i=5; i<s.size(); i++){
if(isdigit(s[i])){
res += s[i];
}
}
int y = stoi(res);
int yi = 0;
for(int j=1; j<len; j++){
if(x == heap[j]){
xi = j;
}
if(y == heap[j]){
yi = j;
}
}
if(xi == yi/2 && xi != 0 && yi != 0){
my += '1';
}else{
my += '0';
}
}
if(s[9] == 'e'){//left
string res = "";
for(int i=5; i<s.size(); i++){
if(isdigit(s[i])){
res += s[i];
}
}
int y = stoi(res);
int yi = 0;
for(int j=1; j<len; j++){
if(x == heap[j]){
xi = j;
}
if(y == heap[j]){
yi = j;
}
}
if(yi*2 == xi && xi != 0 && yi != 0){
my += '1';
}else{
my += '0';
}
}
if(s[9] == 'i'){//right
string res = "";
for(int i=5; i<s.size(); i++){
if(isdigit(s[i])){
res += s[i];
}
}
int y = stoi(res);
int yi = 0;
for(int j=1; j<len; j++){
if(x == heap[j]){
xi = j;
}
if(y == heap[j]){
yi = j;
}
}
if(yi*2+1 == xi && xi != 0 && yi != 0){
my += '1';
}else{
my += '0';
}
}
if(s[9] == 'o'){//root
if(heap[1] == x){
my += '1';
}else{
my += '0';
}
}
}else{
string res = "";
for(int i=5; i<s.size(); i++){
if(isdigit(s[i])){
res += s[i];
}
}
int y = stoi(res);
int yi = 0;
for(int j=1; j<len; j++){
if(x == heap[j]){
xi = j;
}
if(y == heap[j]){
yi = j;
}
}
if(yi/2 == xi/2 && xi != 0 && yi != 0){
my += '1';
}else{
my += '0';
}
}
}
cout << my << endl;
return 0;
}
四、Recycling of Shared Bicycles (30 分)
分析:有n个点,输入m行路径,寻找最短的一条路能从0开始尽量所有点。乱搞出来的,一开始我以为和老题目一样,求一个点的最短路径,其实不然,它没有表明末尾的点,那也就是说每走一步都要去找离自己最近的点,然后正在走的点变成为这个点。我建了个dis的二维数组,将每个点与各个点的最短路径都保存了,然后再一次使用dijkstra算法,每次改变点的位置,找出最短的路径。
#include<bits/stdc++.h>
using namespace std;
const int inf = 99999999;
int dis[220][220], e[220][220];
bool visit[220];
vector<int> pre[220], path, res, my;
int maxr = -1;
int main(){
fill(dis[0], dis[0]+220*220, inf);
fill(e[0], e[0]+220*220, inf);
int n, m, a1, a2, d;
cin >> n >> m;
for(int i=0; i<m; i++){
cin >> a1 >> a2 >> d;
e[a1][a2] = d;
e[a2][a1] = d;
}
int now = 0;
for(int k=0; k<=n; k++){
dis[k][k] = 0;
fill(visit, visit+220, false);
for(int i=0; i<=n; i++){
int u = -1, mini = inf;
for(int j=0; j<=n; j++){
if(visit[j] == false && mini > dis[k][j]){
u = j;
mini = dis[k][j];
}
}
if(u == -1) break;
visit[u] = true;
for(int v=0; v<=n; v++){
if(visit[v] == false && e[u][v] != inf){
if(dis[k][u] + e[u][v] < dis[k][v]){
dis[k][v] = dis[k][u] + e[u][v];
}
}
}
}
}
fill(visit, visit+220, false);
int nnow = 0;
visit[0] = true;
my.push_back(0);
for(int i=0; i<=n; i++){
int mini = inf, u = -1;
for(int k=0; k<=n; k++){
if(nnow != k && visit[k] == false && dis[nnow][k] < mini){
u = k;
mini = dis[nnow][k];
}
}
if(u == -1){
break;
}
visit[u] = true;
my.push_back(u);
nnow = u;
}
for(int i=0; i<my.size(); i++){
if(i != 0) cout << " ";
cout << my[i];
}
cout << endl;
int flag = 0;
for(int i=0; i<=n; i++){
if(dis[0][i] == inf){
if(flag != 0)cout << " ";
cout << i;
flag = 1;
}
}if(flag == 1){
cout << endl;
}
if(flag == 0){
int sum = 0;
for(int i=0; i<my.size()-1; i++){
sum += dis[my[i]][my[i+1]];
}
cout << sum << endl;
}
return 0;
}
总结
两个测试点没过还是挺遗憾的,但想想其实也就刷了两三个星期的pat题,对这个结果也就挺满意了,有机会的话下次再战。