Jouier 普及组十连测 R3
反思
首先,先悔恨一下这次的比赛成绩。
这次比赛的教训就是,简单的题目一定要打不要被复杂的题面震慑到,以及变量名不能是保留字,如第一题的x1,y1,要开long long,计算好数据范围,如第三第四题。
T1
代码思路
暴力枚举宝石矿边上的每一个点(整数,且是边上的点,显而易见边上的点一定比中间的点要近),找出最小值排序输出即可;注意小数精度问题。
AC代码
#include<bits/stdc++.h>
using namespace std;const int N = 1e6+10;
struct Node{double xx,yy;
}a[N];
int xx1,yy1,x22,yy2,n,id; double func(double xx,double yy){double minn = 1e9;for(int i = xx1; i <= x22; i++){minn = min(minn,sqrt(pow(i-xx,2)+pow(yy1-yy,2)));}for(int i = xx1; i <= x22; i++){minn = min(minn,sqrt(pow(i-xx,2)+pow(yy2-yy,2)));}for(int i = yy1; i <= yy2; i++){minn = min(minn,sqrt(pow(xx1-xx,2)+pow(i-yy,2)));}for(int i = yy1; i <= yy2; i++){minn = min(minn,sqrt(pow(x22-xx,2)+pow(i-yy,2)));}return minn;
}int main(){freopen("cow.in","r",stdin);freopen("cow.out","w",stdout);ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);double mn = 1e9;cin >> n >> xx1 >> yy1 >> x22 >> yy2;for(int i = 1; i <= n; i++){cin >> a[i].xx >> a[i].yy;}for(int i = 1; i <= n; i++){double nw = func(a[i].xx,a[i].yy);if(nw < mn){mn = nw;id = i;}printf("%.9lf ",nw);}printf("\n%d",id);return 0;
}
T2
代码思路
首先讲一下如何处理操作1,2,就拿map存每个数出现的次数,存加去减即可。
然后预处理1e5以内的数的因数是哪些,循环遍历x的因数,看看map中是否存在,再计算出最大的k即可。
代码
#include<bits/stdc++.h>
using namespace std;const int N = 1e5+10; map<int,int> mp; //出现次数
vector<vector<int>> a(N); //存因数 void init(){for(int i = 1; i <= N; i++){for(int j = i; j <= N; j += i){a[j].push_back(i);}}
}int mx_k(int d,int x){if(d == 1) return 0;int k = 0;while(x%d == 0){x/=d;k++;}return k;
}int query(int x){int mxx = 0;for(int i = 0; i < a[x].size(); i++){int d = a[x][i];if(d == 1) continue;if(mp.find(d) != mp.end() && mp[d] > 0){int k = mx_k(d,x);if(k > mxx){mxx = k;}}}return mxx;
}int main() {freopen("set.in","r",stdin);freopen("set.out","w",stdout);ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);init();int n,q;cin >> n >> q;for(int i = 1; i <= n; i++){int x; cin >> x;mp[x]++;}while(q--){int op,x;cin >> op >> x;if(op == 1) mp[x]--;else if(op == 2) mp[x]++;else cout << query(x) << endl;}return 0;
}
T3
代码思路
按照题意建边即可,但是第二个建边要求直接暴力会超时,思考一下,可以直接建i到i-1的边跑dijkstra就行了。还要注意数据范围开2e6+10即可。
代码
#include<bits/stdc++.h>
using namespace std;typedef pair<int,int> PII;
const int N =2e6+10;
int h[N],e[N],ne[N],w[N],idx,dist[N];
int n,m;
bool s[N];void add(int a,int b,int c){e[idx] = b;w[idx] = c;ne[idx] = h[a];h[a] = idx;idx++;
} void dijkstra(int st){memset(dist,0x3f,sizeof dist);memset(s,0,sizeof s);dist[st] = 0;priority_queue<PII,vector<PII>,greater<PII> > heap;heap.push({dist[st],st});while(!heap.empty()){auto t = heap.top();heap.pop();int k = t.second,dis = t.first;if(s[k]) continue;s[k] = 1;for(int i = h[k]; i != -1; i = ne[i]){int j = e[i];if(!s[j]){if(dist[j] > dis+w[i]){dist[j] = dis+w[i];heap.push({dist[j],j});}}}}
}int main(){freopen("paths.in","r",stdin);freopen("paths.out","w",stdout);ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); memset(h,-1,sizeof h);cin >> n >> m;for(int i = 1; i < n; i++){int j = i+1;add(i,j,abs(i-j)),add(j,i,abs(i-j));}for(int i = 1; i <= m; i++){int a,b,z; cin >> a >> b >> z;add(a,b,z),add(b,a,z);}dijkstra(1);for(int i = 2; i <= n; i++){cout << dist[i] << " ";}return 0;
}
T4
代码思路
很明显是个dp思路因为要分阶段求最优方案,我们可以看成01背包,因为每个任务只能做一次,而“总背包空间”就是两重约束,其中多余的生命值可以转化为体力值。之后正常dp即可,要注意最优方案我们需要从0枚举到生命值,以及0到体力值+剩余生命值,的最大值即可,还要开long long。
代码
#include<bits/stdc++.h>
using namespace std;int n,H,K;
const int N = 1e3+10;
long long k[N],w[N],h[N],dp[N][N];int main(){freopen("adventure.in","r",stdin);freopen("adventure.out","w",stdout);ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin >> n >> H >> K;for(int i = 1; i <= n; i++) cin >> h[i] >> k[i] >> w[i];for(int i = 1; i <= n; i++){for(int j = H; j >= h[i]; j--){for(int f = H+K-j; f >= k[i]; f--){dp[j][f] = max(dp[j][f],dp[j-h[i]][f-k[i]]+w[i]);}}}long long mxx = -1e9;for(int i = 0; i <= H; i++){for(int j =0; j <= H+K-i; j++){
// cout << dp[i][j] << " ";mxx = max(mxx,dp[i][j]);}
// cout << endl;}cout << mxx << endl;return 0;
}
继续努力,加油!!