普及第六场题解报告

七七七七

https://ac.nowcoder.com/acm/contest/7614/A

普及第六场题解报告

T1

*事实上T1可以打表,这使你充满了决心

#include<bits/stdc++.h>
using namespace std;

int n,sum,i=0,pw=1;

int main(){
    scanf("%d",&n);
    for(i=1;sum<n;++i,pw*=7){
        sum+=pw;
        if(sum>=n) break;
    }
    printf("%d",i);
    return 0;
}

T2

60%的数据:

考虑当前处在第的位置,分两类
第一类:直接走到的位置
第二类:先到一个传送门,再从传送门走到位置
复杂度为

100%的数据:

由于可以从一个位置到达所有传送门的位置
所以可以预处理数组表示从传送门出来到位置的最短路
仍然分为两类
第一类:直接走到
第二类:
复杂度为

#include<bits/stdc++.h>
#define maxn 5010
#define INF 10000010
using namespace std;

int n,m,foot[maxn],X[maxn],Y[maxn],door[maxn],doors[maxn];//foot i  从i去往i+1
long long ans;

int main(){
//    freopen("test.in","r",stdin);
//    freopen("test.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d%d",&X[i],&Y[i]),doors[i]=INF;
    for(int i=1;i<=m;++i) scanf("%d",&door[i]);
    for(int i=1;i<=n;++i){
        if(i<n) foot[i]=abs(X[i]-X[i+1])+abs(Y[i]-Y[i+1]);
        for(int j=1;j<=m;++j){
            int dis=abs(X[i]-X[door[j]])+abs(Y[i]-Y[door[j]]);
            doors[i]=min(doors[i],dis);
        }
    }
    for(int i=1;i<n;++i) ans+=1LL*min(doors[i+1],foot[i]);
    printf("%lld",ans);
    return 0;
}

T3

subtask1

可以打表,但是很累

subtask2

通过dfs枚举每个小球移动的位置,暴力计算出答案

60%的数据

我们考虑这个字符会把整个板子分成许多的空间
对于每一个空间,空间的球是绝对无法到达其他空间的,且整个空间内部只有球和空格
所以对于每个空间的小球进行位置的枚举
我们考虑最优答案是向下移动最多的情况,
对于每一个空间
最终小球会堆积在底部,这肯定是最优的。
而且每次使一个能移动的小球填充最底下的空格,是不会造成道路堵塞的问题的。证明:若每一个小球都不能直接移动到底部,则这不满足一个空间的定义。
枚举这次堆积在底部的球是怎么移动得到的。
复杂度:未知

100%的数据

我们考虑一个空间中的球,个数为,他们的高度为
那么掉落掉底部后他们的高度为
最终得分为

所以不必再用dfs枚举每个小球的位置

#include<bits/stdc++.h>
#define maxn 300010
#define ll long long
using namespace std;

int n,nums,num;
ll sum1,sum2[maxn],ans;
bool Map[maxn][3],v[maxn][3],have[maxn][3];

void dfs(int y,int x){
    if(x<1||x>2||y<1||y>n||v[y][x]||Map[y][x]) return;
    v[y][x]=true;
    if(have[y][x]) sum1+=1LL*y,++num;//计算h的总和
    ++nums;sum2[nums]=sum2[nums-1]+1LL*y;//计算k的前缀
    dfs(y,x-1);//先考虑左右,再考虑上面,因为要使小球尽量堆积在底部
    dfs(y,x+1);
    dfs(y+1,x);
}

int main(){
//    freopen("test.in","r",stdin);
//    freopen("test.out","w",stdout);
    scanf("%d",&n);
    for(int i=n;i>=1;--i){
        for(int j=1;j<=2;++j){
            char c;
            cin>>c;
            if(c=='x') Map[i][j]=true;
            if(c=='o') have[i][j]=true;
        }
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=2;++j){
            if(!v[i][j]){
                dfs(i,j);
                ans+=sum1-sum2[num];
                while(nums--) sum2[nums]=0;
                sum1=0,num=nums=0;
            }
        }
    printf("%lld",ans);
    return 0;
}

T4

基本原理和T2一致

subtask1

dfs大法

subtask2

对于k=0的情况,每次跑单源最短路进行从的最短路线即可

60%的数据

如上述,可以用对每个点跑最短路,然后用T2同理的进行记录,后分类即可

100%的数据

要堆优化的dij处理从每个位置出发的最短路
复杂度

#include<bits/stdc++.h>
#define maxn 2010
#define ll long long
#define INF 10000000000010
using namespace std;

int n,m,k,door[maxn];
ll foot[maxn],doors[maxn],ans;

struct EDGE{
    int nxt,to;
    ll dis;
}edge[maxn<<4];
int head[maxn],edge_num;
void add_edge(int from,int to,ll dis){
    edge[++edge_num].nxt=head[from];
    edge[edge_num].to=to;
    edge[edge_num].dis=dis;
    head[from]=edge_num;
}

ll dis[maxn];
struct node{
    int drop;
    ll dis_sum;
}tmp;
bool operator <(node x,node y){
    return x.dis_sum>y.dis_sum;
}

bool v[maxn];
priority_queue <node> q;
void PusH(int dr,ll d){
    tmp.drop=dr,tmp.dis_sum=d;
    q.push(tmp);
}
void Dij(int s){
    for(int i=1;i<=n;++i) dis[i]=INF,v[i]=false;
    dis[s]=0;
    PusH(s,0);
    while(!q.empty()){
        ll dis_sum=q.top().dis_sum;int x=q.top().drop;
        q.pop();
        if(v[x]) continue;
        v[x]=true;
        for(int i=head[x];i;i=edge[i].nxt){
            int gr=edge[i].to;
            if(dis[gr]>edge[i].dis+dis_sum){
                dis[gr]=edge[i].dis+dis_sum;
                PusH(gr,dis[gr]);
            }
        }
    }
}


int main(){
//    freopen("test.in","r",stdin);
//    freopen("test.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;++i) doors[i]=INF;
    for(int i=1;i<=m;++i){
        int a,b;ll c;
        scanf("%d%d%lld",&a,&b,&c);
        add_edge(a,b,c);
        add_edge(b,a,c);
    }
    for(int i=1;i<=k;++i) scanf("%d",&door[i]);
    for(int i=1;i<=n;++i){
        Dij(i);
        if(i<n) foot[i]=dis[i+1];
        for(int j=1;j<=k;++j)
            doors[i]=min(doors[i],dis[door[j]]);
    }
    for(int i=1;i<n;++i) ans+=min(doors[i+1],foot[i]);
    printf("%lld",ans);
    return 0;
}
全部评论

相关推荐

2 收藏 评论
分享
牛客网
牛客企业服务