牛客算法周周练3 ABCDE 分层图最短路
A:
思路:直接bfs就可以了。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
char a[105][105][105];
struct node{
int x, y, z, k;
};
queue<node> q;
int ans=-1;
void BFS(int n){
q.push(node{1, 1, 1, 1});
a[1][1][1]='*';
while(!q.empty()){
node t=q.front(); q.pop();
if(t.x==n&&t.y==n&&t.z==n){
ans=t.k;
return ;
}
for(int i=-1; i<2; i++){
for(int j=-1; j<2; j++){
for(int k=-1; k<2; k++){
int x=t.x+i, y=t.y+j, z=t.z+k;
if(((i==0&&j==0)||(i==0&&k==0)||(j==0&&k==0))&&x>=1&&x<=n&&y>=1&&y<=n&&z>=1&&z<=n&&a[x][y][z]!='*'){
q.push(node{x, y, z, t.k+1});
a[x][y][z]='*';
}
}
}
}
}
}
int main(){
int n; scanf("%d%*c", &n);
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
for(int k=1; k<=n; k++){
scanf("%c", &a[i][j][k]);
}
getchar();
}
}
BFS(n);
printf("%d\n", ans);
return 0;
}
B:
思路:
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod=2333;
int a[3005][3005];
LL f[3005][3005];
int main(){
int n, m; scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d", &a[i][j]);
}
}
for(int i=n; i>=1; i--){
for(int j=1; j<=m; j++){
if(a[i][j]==1) continue;
if(i==n&&j==1) f[i][j]=1;
else f[i][j]=(f[i+1][j]+f[i][j-1])%mod;
}
}
printf("%lld\n", f[1][m]);
return 0;
}
C:
建立m+1层图,前面m层是每条地铁线。因为每层之间可能公用了一些节点。我们之间让他们向虚拟节点连就可以了,i->(m * n+i)代价为0, (m * n+i)->i代价为a。
那么m * n+s->m * n+j就是题目的要求
#include <bits/stdc++.h>
using namespace std;
#define LL long long
vector<vector<pair<int, int> > > ve(600005);
int dis[600005]; //dis当前的最短路
int vis[600005]; //是否已经求出最短路
priority_queue<pair<int, int> > q;
int dijkstra(int s, int t){
while(!q.empty()) {
q.pop();
}
dis[s]=0;
q.push(make_pair(-dis[s], s));
while(!q.empty()){
int now=q.top().second;q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int i=0; i<ve[now].size();i++){
int v=ve[now][i].first;
if(!vis[v]&&dis[v]>dis[now]+ve[now][i].second){
dis[v]=dis[now]+ve[now][i].second;
q.push(make_pair(-dis[v], v));
}
}
}
if(dis[t]==dis[0]) return -1;
else return dis[t];
}
int main(){
int n, m, s, t; scanf("%d%d%d%d", &n, &m, &s, &t);
memset(dis, 7, sizeof(dis));
for(int i=0; i<m; i++){
int a, b, c; scanf("%d%d%d", &a, &b, &c);
int x=0, y=0;
for(int k=0; k<c; k++){
scanf("%d", &y);
if(k!=0){
ve[x+i*n].push_back({y+i*n, b});
ve[y+i*n].push_back({x+i*n, b});
}
ve[y+i*n].push_back({y+m*n, 0});
ve[y+m*n].push_back({y+i*n, a});
x=y;
}
}
cout<<dijkstra(n*m+s, n*m+t)<<endl;
return 0;
}D:
思路:用2个栈,一个放数字,一个放运算符。遇到就把数字栈里面的2个数放回栈。最后数字栈里面全部相加就可以了。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int mod=10000;
char s[600005];
char op[600005];
LL x[600005], ts=0, tp=0;
int main(){
scanf("%s", s+1);
int n=strlen(s+1);
for(int i=1; i<=n; ){
if(s[i]=='+'||s[i]=='*'){
op[++tp]=s[i];
i++;
}
else{
LL ans=0;
while(i<=n&&s[i]>='0'&&s[i]<='9'){
ans=ans*10+s[i]-'0';
i++;
}
x[++ts]=ans%mod;
if(op[tp]=='*'){
tp--; x[ts-1]=x[ts]*x[ts-1]%mod;
ts--;
}
}
}
while(ts){
x[ts-1]=(x[ts]+x[ts-1])%mod;
ts--;
}
cout<<x[1]<<endl;
return 0;
}E:
思路:我们考虑从小到大枚举乳液的SPI,那么可能和他分配的牛[l, r]的l<=PSI<=r。但是我们贪心一定把它分配给是r最小的。因为r更大的可以和SPI更大的分配。如果SPI>r那么这头牛就不可能得到,因为后面的SPI更大,更不可能分配到。
用优先队列来维护牛的r就可以了。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
struct node{
int l, r;
}a[2505], b[2505];
priority_queue<int, vector<int>, greater<int> > q;
int main(){
int n, m; scanf("%d%d", &n, &m);
for(int i=1; i<=n; i++){
scanf("%d%d", &a[i].l, &a[i].r);
}
for(int i=1; i<=m; i++){
scanf("%d%d", &b[i].l, &b[i].r);
}
sort(b+1, b+1+m, [](node &a, node &b){return a.l<b.l;});
sort(a+1, a+1+n, [](node &a, node &b){return a.l<b.l;});
int tot=1, ans=0;
for(int i=1; i<=m; i++){
int cut=b[i].r;
while(tot<=n&&a[tot].l<=b[i].l){
q.push(a[tot].r); tot++;
}
while(cut&&!q.empty()){
if(q.top()>=b[i].l){
ans++; cut--;
}
q.pop();
}
}
cout<<ans<<endl;
return 0;
}
查看10道真题和解析