牛客算法週週練3全部題解

比賽傳送門

A-Jelly

題意:三維bfs,從(1,1,1)到(n,n,n)的最短距離
題解:bfs,寫的有點醜,還wa了一發。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int Maxn=5e5+10;
ll read(){
    ll f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
char s[110][110][110];
int disx[6],disy[6],disz[6];
int vis[110][110][110];
struct arr{
	int x,y,z;
};
queue<arr>q;
int n;
void bfs(int x,int y,int z){
	arr node;
	node.x=x,node.y=y,node.z=z;
	q.push(node);
	vis[1][1][1]=0;
	while(!q.empty()){
		arr no=q.front();q.pop();
		if(no.x==n && no.y==n && no.z==n){
			vis[no.x][no.y][no.z]++;
			return;
		}
		for(int i=0;i<6;i++){
			int nx=no.x+disx[i];
			int ny=no.y+disy[i];
			int nz=no.z+disz[i];
			if(nx<=0 || ny<=0 || nz<=0 || nx>n || ny>n || nz>n)continue;
			if(vis[nx][ny][nz] || s[nx][ny][nz]=='*')continue;
			vis[nx][ny][nz]=vis[no.x][no.y][no.z]+1;
			arr nw;
			nw.x=nx,nw.y=ny,nw.z=nz;
			q.push(nw);
		}
	}
}
int main(){
	disx[0]=1;disy[0]=0;disz[0]=0;
	disx[1]=0;disy[1]=1;disz[1]=0;
	disx[2]=0;disy[2]=0;disz[2]=1;
	disx[3]=-1;disy[3]=0;disz[3]=0;
	disx[4]=0;disy[4]=-1;disz[4]=0;
	disx[5]=0;disy[5]=0;disz[5]=-1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				cin>>s[i][j][k];
	bfs(1,1,1);
	if(vis[n][n][n]==0)puts("-1");
	else printf("%d\n",vis[n][n][n]);
	return 0;
}

B-[木]迷霧森林

題意:n*m的圖,從左下角走到右上角的全部方案,1不能走,0能走。
題解:常做的題目是從左上走到右下,那個題目的狀態轉移方程爲fi,j=fi1,j+fi,j1f_{i,j}=f_{i-1,j}+f_{i,j-1}此題同理,稍微改改就可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int Maxn=5e5+10;
ll read(){
    ll f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
int n,m;
int a[3030][3030];
int p=2333; 
int f[3030][3030];
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			a[i][j]=read();
	f[n][1]=1;
	for(int i=n-1;i>=1;i--)
		if(a[i][1]==1)break;
		else f[i][1]=f[i+1][1]%p;
	for(int i=2;i<=m;i++)
		if(a[n][i]==1)break;
		else f[n][i]=f[n][i-1]%p;
	for(int i=n-1;i>=1;i--)
		for(int j=2;j<=m;j++)
			if(a[i][j]==1)continue;
			else f[i][j]=(f[i+1][j]+f[i][j-1])%p; 
	printf("%d\n",f[1][m]);
	return 0;
}

C-小雨坐地鐵

題意:最難的一道題了,題目還挺長的,自己讀讀吧。
題解:自己畫畫圖,會發現其實就是一道求最短路的題目是一道分層最短路+虛點。每次中轉就是當前點到虛點,其花費爲a,其餘就是正常分層建圖即可,然後dis的大小和邊的數量要注意。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int Maxn=5e5+10;
ll read(){
    ll f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
struct Edge{
    int to,next,w;
}l[maxn];
struct Node{
    int no,dis;
    friend bool operator < (Node x,Node y){
        return x.dis>y.dis;
    }
}a[maxn];
int head[maxn],cnt,cur,dis[maxn];
bool vis[maxn];
priority_queue<Node> q;
void add(int x,int y,int z){
    cnt++;
    l[cnt].to=y,l[cnt].w=z,l[cnt].next=head[x];
    head[x]=cnt;
}
int n,m,S,T;
int main(){
    scanf("%d%d%d%d",&n,&m,&S,&T);
    for(int i=1;i<=m;i++){
        int a,b,c,pre;
        scanf("%d%d%d",&a,&b,&c);
        for(int j=1;j<=c;j++){
            int x;
            scanf("%d",&x);
            add((i-1)*n+x,n*m+x,0);
            add(n*m+x,(i-1)*n+x,a);
            if(j!=1){
                add((i-1)*n+pre,(i-1)*n+x,b);
                add((i-1)*n+x,(i-1)*n+pre,b);
            }
            pre=x;
        }
    }
    int s=n*m+S,t=n*m+T;
    for(int i=1;i<=n*m+n+n;i++)a[i].dis=INF,a[i].no=i;
    a[s].dis=0;cur=s;
    q.push(a[s]);
    while(!q.empty()){
        cur=q.top().no;
        q.pop();
        if(vis[cur])continue;
        vis[cur]=1;
        for(int i=head[cur];i;i=l[i].next){
            if(a[l[i].to].dis>a[cur].dis+l[i].w){
                a[l[i].to].dis=a[cur].dis+l[i].w;
                q.push(a[l[i].to]);
            }
        }
    }
    if(a[t].dis<INF)printf("%d\n",a[t].dis);
    else puts("-1");
    return 0;
}

D-表達式求值

題意:給出一個只有+和的算式,求出其值。
題解:C++做法是拿棧做,遇到
額外保留一個數即可,不知道爲什麼wa了。所以就用了python。python的話就是一行代碼的事。

print input()%10000

E-suncreen

題意:用n組集合和m組數字,要使得數字儘可能匹配到集合之中。
題解:如果n和m夠大,就需要用到優先隊列了。但是n和m只有2500,排序之後平方暴力即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
const int Maxn=5e5+10;
ll read(){
    ll f=1,x=0;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    return f*x;
}
struct arr{
	int l,r;
    friend bool operator < (arr x,arr y){
        return x.r<y.r;
    }
}cow[3000];
struct brr{
	int val,num;
    friend bool operator < (brr x,brr y){
        return x.val<y.val;
    }
}sun[3000];
int n,m;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d%d",&cow[i].l,&cow[i].r);
	for(int i=1;i<=m;i++)scanf("%d%d",&sun[i].val,&sun[i].num);
	sort(cow+1,cow+1+n);
	sort(sun+1,sun+1+m);
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(cow[i].l<=sun[j].val && cow[i].r>=sun[j].val && sun[j].num>0){
				ans++;
				sun[j].num--;
				break;
			}
			if(sun[j].val>cow[i].r)break;
		}
	}
	printf("%d\n",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章