【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
【LGR-148-Div.3】洛谷基础赛 #1 & MGOI Round I
T1 luoguP9502 『MGOI』Simple Round I | A. 魔法数字 \(100pts\)
-
水题,场切了。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' int main() { int n,m; cin>>n; m=log2(n); if((1<<m)==n) { if(m%2==1) { m--; } else { m-=2; } } else { if(m%2==1) { m--; } } cout<<m; return 0; }
T2 luoguP9503 『MGOI』Simple Round I | B. 魔法照相馆 \(100pts\)
-
水题,赛场上不会位运算,就当成大模拟打了,码风凑合看吧,谨慎观看此代码。
-
可以将 \(if,else\) 压成位运算。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' int main() { ll n,i,ans=0,r=1,b=1,w=1; char pd,en='W'; cin>>n; for(i=1;i<=n;i++) { cin>>pd; if(pd!=en) { if(en=='W') { if(pd=='B') { if(b==1) { ans++; } else { ans+=2; b=1; } w=0; } if(pd=='R') { if(r==1) { if(b==1) { ans+=2; b=0; } else { ans++; } } else { if(b==1) { ans+=3; b=0; } else { ans+=2; } } w=0; r=1; } } if(en=='B') { if(pd=='R') { if(r==1) { ans++; } else { ans+=2; r=1; } b=0; r=1; } if(pd=='W') { ans+=1; w=1; } } if(en=='R') { if(pd=='W') { ans+=1; w=1; } if(pd=='B') { ans+=1; b=1; } } en=pd; } } cout<<ans; return 0; }
T3 luoguP9504 『MGOI』Simple Round I | C. 魔法禁林 \(0pts\)
- 注意 \(0\le w\le 100\) 这个条件,又因为 扣血方式为\(\left\lfloor \frac{w_i}{k} \right\rfloor\) ,所以易知最多跑 \(100\) 条边(因为 \(k>w_i\) 就不扣血了,能够无伤走到终点,直接返回记录答案即可),故魔力值 \(\le 100\) 。
- 正解:以 \(t\) 为起点, \(s\) 为终点,便于确定 \(k\) 的值,跑单源最短路。
- 考虑给 \(dijkstra\) 中的 \(dis\) 数组增加一维,令 \(dis[i][j]\) 表示当 \(k=i\) 时,走到 \(j\) 的最小生命值。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' struct node { int nxt,to,w; }e[90000]; int head[90000],vis[110][90000],dis[110][90000],cnt=0,ans=0x7f7f7f7f; void add(int u,int v,int w) { cnt++; e[cnt].nxt=head[u]; e[cnt].to=v; e[cnt].w=w; head[u]=cnt; } void dijkstra(int s) { int x,num,i; priority_queue<pair<int,pair<int,int> > >q; memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[0][s]=0; q.push(make_pair(0,make_pair(0,-s))); while(q.empty()==0) { num=-q.top().second.first; x=-q.top().second.second; q.pop(); if(num>100)//当走的边数大于100时,直接返回 { ans=min(ans,dis[num][x]); } else { if(vis[num][x]==0) { vis[num][x]=1; for(i=head[x];i!=0;i=e[i].nxt) { if(dis[num+1][e[i].to]>dis[num][x]+e[i].w/(num+1)) { dis[num+1][e[i].to]=dis[num][x]+e[i].w/(num+1); q.push(make_pair(-dis[num+1][e[i].to],make_pair(-(num+1),-e[i].to))); } } } } } } int main() { int n,m,s,t,u,v,w,i; cin>>n>>m>>s>>t; for(i=1;i<=m;i++) { cin>>u>>v>>w; add(u,v,w); add(v,u,w); } dijkstra(t); for(i=0;i<=101;i++) { ans=min(ans,dis[i][s]); } cout<<ans<<endl; return 0; }
T4 luoguP9505 『MGOI』Simple Round I | D. 魔法环 \(0pts\)
- 因为涉及变量重复问题,题面中的 \(k\) 此处用 \(m\) 代替。
- 考虑破坏为链,进行 \(DP\) ,枚举以每个点为起点,令 \(f[i][j]\) 表示前 \(i\) 个中激活了 \(j\) 个精灵产生的附魔值的最小值,枚举上一个被激活的精灵 \(k(1\le k <i)\) 进行状态转移,
- 得到在 \(1\le j \le i\le n,j<m\) 时, \(f[i][j]=min(f[i][j],f[k][j-1]+max(b[k],b[i])×\sum\limits_{h=1}^{i-k-1}h+b[i]^2)\)。
- 得到在 \(m\le i\le n,j=m\) 时, 因为要满足 至少 激活 \(m\) 个精灵,\(f[i][j]=min(f[i][j],f[k][m]+max(b[k],b[i])×\sum\limits_{h=1}^{i-k-1}h+b[i]^2)\)。
- 这样的复杂度为 $O(n^3k) $,成功 \(\huge TLE\) 。
- 有个贪心的结论,激活魔供值为 \(0\) 的精灵一定不劣(因为是否激活 \(0\) 对答案没有影响)。故直接考虑以 \(0\) 为起点,故 \(f[1][1]=0^2=0\) ,接着进行状态转移。时间复杂度 \(O(n^2k)\) ,卡着时限过。
#include<bits/stdc++.h> using namespace std; #define ll long long #define sort stable_sort #define endl '\n' ll a[3001],b[3001],f[3001][101];//十年OI一场空,不开long long见祖宗 int main() { ll n,m,i,j,k,rt,ans=0x7f7f7f7f; cin>>n>>m; memset(f,0x3f,sizeof(f));//初始化 f[1][1]=0; for(i=1;i<=n;i++) { cin>>a[i]; if(a[i]==0) { rt=i; } } for(i=1;i<=n;i++)//以0为起点,重新构造 { b[i]=a[(i+rt-2)%n+1]; } for(i=1;i<=n;i++) { for(j=2;j<=min(i,m);j++) { for(k=1;k<=i-1;k++) { f[i][j]=min(f[i][j],f[k][j-1]+(i-k-1)*(i-k)/2*max(b[k],b[i])+b[i]*b[i]); if(j==m) { f[i][j]=min(f[i][j],f[k][j]+(i-k-1)*(i-k)/2*max(b[k],b[i])+b[i]*b[i]); } } } } for(i=m;i<=n;i++) { ans=min(ans,f[i][m]+(n-i)*(n-i+1)/2*b[i]); } cout<<ans<<endl; return 0; }
总结
看清楚题再交,不要像我一样好几次把 \(T3\) 代码交到了 \(T4\) 。
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/17609758.html,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。