zoukankan      html  css  js  c++  java
  • 8.6模拟赛

    T1.最短路path

    求经过k个必经点的最短路

    100%的数据n<=50000,m<=100000,0<=k<=10,1<=z<=5000。

    写了naive的算法,类似分层图的状压最短路,然而加成了双向边,炸成10分,感谢良心出题人。

    正解考虑k+1个点到终点的最短路,+的1是起点,然后它们之间用状压DP求出彼此最短路,再加上到终点的最短路即为答案。

    答案会超过MAX_INT

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define int long long
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    int n,m,num,s,t;
    int lim[16];
    
    const int MAXN=50005;
    
    struct Edge{
        int next,to,w;
    }e[MAXN<<1];
    int ecnt,head[MAXN];
    inline void add(int x,int y,int w){
        e[++ecnt].next = head[x];
        e[ecnt].to = y;
        e[ecnt].w = w;
        head[x] = ecnt;
    }
    struct Node{
        int id,w;
        Node(int x=0,int y=0){id=x;w=y;}
        bool operator<(const Node &rhs)const {
            return w>rhs.w;
        }
    }top;
    bool vis[MAXN];
    int dis[MAXN][12];
    priority_queue<Node> Q;
    void dij(int st,int cur){
        memset(vis,0,sizeof(vis));
        while(!Q.empty()) Q.pop();
        dis[st][cur]=0;Q.push(Node(st,0));
        while(!Q.empty()){
            top=Q.top();
            Q.pop();
            int mn=top.w,mnid=top.id;
            if(dis[mnid][cur]!=mn) continue;
            vis[mnid]=1;
            for(int j=head[mnid];j;j=e[j].next){
                int v=e[j].to;
                if(mn+e[j].w<dis[v][cur]){
                    dis[v][cur]=mn+e[j].w;
                    Q.push(Node(v,dis[v][cur]));
                }
            }
        }
    }
                
    int f[1<<12][12];
    signed main(){
        n=rd();m=rd();num=rd();s=rd();t=rd();
        int x,y,w;
        for(int i=1;i<=m;i++){
            x=rd();y=rd();w=rd();
            add(x,y,w);
        }
        for(int i=1;i<=num;i++){
            lim[i]=rd();
        }
        memset(dis,0x3f,sizeof(dis));
        for(int i=1;i<=num;i++){
            dij(lim[i],i);
        }
        lim[num+1]=s;
        dij(s,num+1);
        memset(f,0x3f,sizeof(f));
        for(int i=1;i<=num+1;i++) f[1<<(i-1)][i]=dis[lim[i]][num+1];
        for(int i=0;i<(1<<(num+1));i++){
            for(int j=1;j<=num+1;j++){
                if(!(i&(1<<(j-1)))) continue;
                for(int k=1;k<=num+1;k++){
                    if(i&(1<<(k-1))) continue;
                    f[i|(1<<(k-1))][k]=min(f[i|(1<<(k-1))][k],f[i][j]+dis[lim[k]][j]);
                }
            }
        }
        int ans=1ll<<60;
        for(int i=1;i<=num+1;i++){
            ans=min(ans,f[(1<<(num+1))-1][i]+dis[t][i]);
        }
        printf("%lld",ans==1ll<<60?-1:ans);
        return 0;
    }
    T1

    T2.剑与魔法(dragons)

    一些前缀限制(前缀不能选超过xi个数),最后一个不限制,还是hsz最巨。

    您最强。

    这是一个贪心,写了一个O(n^2)DP,还没考虑最后一个不限制..

    用小根堆维护选出的数,遇到限制就不断pop直到符合限制,可以证明,最后剩下的就是最优解了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    priority_queue<int> Q;
    int n;
    
    int main(){
        n=rd();
        char s[50];
        for(int i=1;i<=n-1;i++){
            scanf("%s",s);
            if(s[0]=='c') Q.push(-rd());
            else{
                int lim=rd();
                while(Q.size()>=lim) Q.pop();
            }
        }
        int ans=0;
        while(!Q.empty()) ans-=Q.top(),Q.pop();
        cout<<ans;
        return 0;
    }
    T2

     T3.三角形(triangle)

    给出n个点,问可以构成多少个三角形。

    求共线点对数量,暴力O(n^3)

    可以枚举一个点,计算出其他所有点的斜率,取相同段长为xi,ans-=sigma(C(xi,2))

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=3005;
    
    int n;
    int x[MAXN],y[MAXN];
    
    double a[MAXN];
    int p;
    long long ans;
    
    int tmp;
    int main(){
    //    freopen("triangle.in","r",stdin);
    //    freopen("triangle.out","w",stdout);
        n=rd();
        ans=1ll*n*(n-1)*(n-2)/6;
        for(int i=1;i<=n;i++) x[i]=rd(),y[i]=rd();
        for(int i=1;i<=n;i++){
            tmp=0;p=0;
            for(int j=i+1;j<=n;j++){
                if(x[j]-x[i]==0) tmp++;
                else a[++p]=1.0*(y[j]-y[i])/(x[j]-x[i]);
            }
            sort(a+1,a+1+p);
            a[p+1]=19491001.19491001;
            int cnt=1;
            for(int j=2;j<=p+1;j++){
                if(a[j]==a[j-1]) cnt++;
                else{
                    ans-=1ll*(cnt*(cnt-1)/2);
                    cnt=1;
                }
            }
            ans-=1ll*(tmp*(tmp-1)/2);
        }
        
        cout<<ans;
        return 0;
    }
    T3

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9433609.html

  • 相关阅读:
    STL整理之map
    链表及数组模拟链表
    树链剖分详解
    Luogu P3879 【[TJOI2010]阅读理解】
    Luogu P2727 【01串 Stringsobits】
    CF1200D 【White Lines】
    Luogu P4945 【最后的战役】
    Luogu P4944 【PION贪吃蛇】
    Luogu P2426 【删数】
    P2163 【[SHOI2007]园丁的烦恼】
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9433609.html
Copyright © 2011-2022 走看看