第十四届程序设计竞赛 D H

问题 D: Rorororobot

比赛时没看懂题目,错失良机
题意:问从一点x是否能到另一点y,约束每次走k格,且不能出界和碰墙
算法:st表
因为判断不能比较简单,所以先判断NO
1.如果坐标相差不满足k的倍数一定不能过
2.如果两则之间隔了一道墙,需要判断是否可行
2.1 算出两者之间最高的墙时间复杂度太高,考虑st表,o(1)直接算出
2.2 判断绕行的最高点是否满足k的倍数

神奇的代码
int a[N];
int f[N][20];
int n,m;
//st表模板
void get_f(){
    for(int i=1;i<=m;i++) f[i][0]=a[i];
    for(int j=1;j<=20;j++){
        for(int i=1;i+(1<<j)-1<=m;i++){
            f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
}
void bu_f(){
    n=read(),m=read();
    for(int i=1;i<=m;i++) a[i]=read();
    get_f();//st表
    int q=read();
    while(q--){
        int xx1=read(),yy1=read(),xx2=read(),yy2=read(),k=read();
        //两者距离要相差k
        if(abs(xx1-xx2)%k||abs(yy1-yy2)%k){
            cout<<"NO\n";
            continue;
        }
		//交换,方便计算
        if(yy1>yy2) {
            swap(yy1,yy2);
            swap(xx1,xx2);
        }
        //o(1)求区间最大值
        int k1=log2(yy2-yy1+1);
        int mx=max(f[yy1][k1],f[yy2-(1<<k1)+1][k1]);
        //判断,如果过不去直接退出
        if((mx==n)||(a[yy1]==xx1)||(a[yy2]==xx2)){
            cout<<"NO\n";
            continue;
        }
        //需要绕行
        if(mx>xx1&&mx>xx2){
            int f=0;
            //判断是否可以绕行,从天花板开始,枚举是否可行
            for(int i=n;i>mx;i--){
                if(abs(i-xx1)%k==0&&(abs(i-xx2)%k==0)){
                    f=1;
                    break;
                }
            }
            if(f){
                cout<<"YES\n";
            }
            else cout<<"NO\n";
            continue;
        }
        //其他直接过
        cout<<"YES\n";
    }  
}

问题 H: 浙外办会展

此题对时间复杂度的要求好高,数组大小n*k(1e7)和时间复杂度n * k * logk(1e7-1e8)有点极限

思路:
题意从k种选s种,问最小代价
1.我们可以开二维数组ans[n][k],表示每个点i选种类是j的最小代价
2.这个可以bfs,算完之后,只需要sort从小到大,累加求和即可

如果你想到了这里,很遗憾,超时8%

分析,每个点都遍历一下,时间复杂度是n^2 肯定过不了;
考虑优化
我们发现很多点的种类是一样的,相当于多个源点向外扩散,每个点的最小值是距离源点最近的那个点,没错可以利用上次学到的优先队列维护最小值,时间复杂的为n* logn,可以。

一点点细节
int a[N];
int n,m,s,k;
vector<int> g[N];
int ans[N][105];
int vis[N][105];
struct node{
    int dis,id,idx;//距离,国家,种类
    bool operator < (const node &b)const{
        return dis>b.dis;
    }
};
priority_queue<node> q;
int bfs(){
    while(q.size()){
        auto t=q.top();
        q.pop();
        int dis=t.dis,id=t.id,idx=t.idx;
        if(vis[id][idx]) continue;
        vis[id][idx]=1;
        for(int v:g[id]){
            if(ans[id][idx]+1<ans[v][idx]){
                ans[v][idx]=ans[id][idx]+1;
                q.push({ans[v][idx],v,idx});
            }
        }
    }

}
void bu_f(){
    n=read(),m=read(),k=read(),s=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<=m;i++){
        int x=read(),y=read();
        g[x].push_back(y);
        g[y].push_back(x);
    }
    memset(ans,INF,sizeof ans);
    for(int i=1;i<=n;i++){
        ans[i][a[i]]=0;//源点为0
        q.push({0,i,a[i]});//压入队列
    }
    bfs();
    for(int i=1;i<=n;i++){
        sort(ans[i]+1,ans[i]+k+1);//排序
        ll sum=0;
        for(int j=1;j<=s;j++){
            sum+=ans[i][j];//累加求和
        }
        write(sum);
        printf(" ");
    }
}
posted @ 2023-12-25 18:40  不o凡  阅读(39)  评论(0)    收藏  举报