• 南阳CCPC补题:UESTC 1225(dp……另附对拍器)+UESTC 1220(最短路,费用流)+UESTC 1219(高斯消元)


    1225

    题目:有一栋楼,每层楼上有t个人打网球,有p个人游泳,但是每层只能建一种健身设施。每个人的花费是他到最近的对应设施的楼层距离。问最小总花费。

    思路:dp[i][j][k]表示做到第i层的时候选j,和j不同的设施最近在第k层的最小花费,那么如果该层选得和上面一样那么k不变,这个好转移。如果和上一层不一样,那么k层到当前层i的玩家会有一部分重新分布(他们的选择显然以中点为准),这个需要预处理一下(我写得很恶心。。。)。然后wa了整整一天,最后找了个代码对拍了一下才过(基本上完全是对的,,有个初始化没做。。。真是哔了狗。。)。这个对拍器真是好使啊。。。。

    丑陋的代码。。

    /*
    * @author:  Cwind
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-10)
    #define IINF (1<<29)
    #define LINF (1ll<<49)
    #define INF (1000000300)
    #define FINF (1e9)
    #define clr(x) memset((x),0,sizeof (x))
    #define cp(a,b) memcpy((a),(b),sizeof (b))
    #define mset(x,v) memset((x),(v),sizeof (x))
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> P;
    
    const int maxn=5000;
    int T;
    int n;
    ll t[maxn],p[maxn];
    ll ts[2][maxn],ps[2][maxn];
    ll tmm[2][maxn],pm[2][maxn];
    ll dp[2][2][maxn];
    void cal(){
        for(int i=1;i<=n;i++){
            ts[0][i]=ts[0][i-1]+t[i];
            ps[0][i]=ps[0][i-1]+p[i];
            tmm[0][i]=tmm[0][i-1]+t[i]*i;
            pm[0][i]=pm[0][i-1]+p[i]*i;
        }
        ts[1][n+1]=ps[1][n+1]=0;
        tmm[1][n+1]=pm[1][n+1]=0;
        for(int i=n;i>=1;i--){
            ts[1][i]=ts[1][i+1]+t[i];
            ps[1][i]=ps[1][i+1]+p[i];
            tmm[1][i]=tmm[1][i+1]+t[i]*(n-i+1);
            pm[1][i]=pm[1][i+1]+p[i]*(n-i+1);
        }
    }
    ll get(bool o,int l,int r){
        int m=(r+l)/2;
        if(o){
            if(l==0) return tmm[1][1]-tmm[1][r+1]-(ts[1][1]-ts[1][r+1])*(n-r+1);
            ll oc=tmm[0][r]-tmm[0][l-1]-(ts[0][r]-ts[0][l-1])*l;
            ll nc=tmm[0][m]-tmm[0][l-1]-(ts[0][m]-ts[0][l-1])*l+tmm[1][m+1]-tmm[1][r+1]
                    -(ts[1][m+1]-ts[1][r+1])*(n-r+1)+t[r]*(r-l);
            return nc-oc;
        }else{
            if(l==0) return pm[1][1]-pm[1][r+1]-(ps[1][1]-ps[1][r+1])*(n-r+1);
            ll oc=pm[0][r]-pm[0][l-1]-(ps[0][r]-ps[0][l-1])*l;
            ll nc=pm[0][m]-pm[0][l-1]-(ps[0][m]-ps[0][l-1])*l+pm[1][m+1]-pm[1][r+1]
                    -(ps[1][m+1]-ps[1][r+1])*(n-r+1)+p[r]*(r-l);
            return nc-oc;
        }
    }
    int cas;
    int main(){
        //freopen("/home/slyfc/CppFiles/in","r",stdin);
        //freopen("/home/slyfc/CppFiles/out","w",stdout);
        cin>>T;
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++)      
                scanf("%lld%lld",&t[i],&p[i]);
            cal();
            for(int i=0;i<2;i++)
                for(int k=0;k<2;k++)
                    for(int j=0;j<maxn;j++)
                        dp[i][k][j]=LINF;
            dp[0][0][0]=dp[0][1][0]=0;
            dp[1][0][0]=dp[1][1][0]=0;
            bool f=0;
            for(int i=2;i<=n;i++){
                f^=1;
                for(int j=1;j<i-1;j++){
                    dp[f][0][j]=dp[f^1][0][j]+p[i]*(i-j);
                    dp[f][1][j]=dp[f^1][1][j]+t[i]*(i-j);
                }
                for(int j=0;j<i-1;j++){
                    dp[f][0][i-1]=min(dp[f][0][i-1],dp[f^1][1][j]+p[i]+get(1,j,i));
                    dp[f][1][i-1]=min(dp[f][1][i-1],dp[f^1][0][j]+t[i]+get(0,j,i));
                }
            }
            ll ans=LINF;
            for(int i=1;i<n;i++){
                ans=min(ans,dp[f][1][i]);
                ans=min(ans,dp[f][0][i]);
            }
            printf("Case #%d: %lld
    ",++cas,ans);
        }
        return 0;    
    }
    View Code

    对拍器

    while true; do
    ./make>inData #出数据
    ./myCpp<inData>myOut #被测程序
    ./stdCpp<inData>stdOut #正确(暴力)程序
    if diff myOut stdOut; then #比较两个输出文件
    printf AC #结果相同显示AC
    else
    echo WA #结果不同显示WA,并退出
    #cat tmp.out tmp2.out
    exit 0
    fi #if的结束标志,与C语言相反,0为真
    done # while的结束标志
    
    #BY NICK WONG 2014-08-29
    #在终端下,进入当前目录,输入"sh ./nick.sh",(其中nick.sh为当前shell脚本名) '#'表示单行注释
    #diff在两文件相同时返回空串

    对拍器转自:http://blog.csdn.net/nickwong_/article/details/38931579

    1220

    题目:曹操和袁绍决战,曹操当然想赢啦。但是袁绍势力太大,曹操征兵也会有同样多的人跑去袁绍那边= =。有M个战场,N个村庄。曹操在村庄i征一个兵花费w,可以送到x战场去,同时有同样数量的兵会跑去y战场的袁绍阵营。每个战场有个重要度,重要度为0表示无所谓输赢,为1表示不能输(己方人数不少于敌方),为2表示己方人数必须大于敌方。问能否赢和最小花费。

    思路:考虑每个战场己方的净人数,那么实际上征兵对应于x战场增加1,y战场减少1,最后重要战场的净人数大于1(实际上肯定是正好为1)。那么可以建图跑费用流,每个y向x连边,s向重要度0的连边,重要度为2的向t连边。这样每个重要度1的点由于不会与s和t连边,净流为0(人数为0)。重要度为2的点满流(流量1)可以胜利。对应的由于连出s的边净流量不为0,正好对应着重要度为0的点(流量任意)。然后这样会t。实际上费用流是每次沿最短路增广的做法,这个题实际上也是最短路。因为实际上本题不会出现已经分配的流量再退回去的情况。对于任何一条从s到重要度2的点的最短路,必然从重要度为0的点出发,途径若干重要度1的点最后到达重要读2的点。这个过程中总流量没有限制,增加的费用其实是最短路的长度。对应从起点转移1个人到终点,中间点的人数并没有变化(净人数的想法很关键!!)

    /*
    * @author:  Cwind
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-10)
    #define IINF (1<<29)
    #define LINF (1ll<<49)
    #define INF (1000000300)
    #define FINF (1e9)
    #define clr(x) memset((x),0,sizeof (x))
    #define cp(a,b) memcpy((a),(b),sizeof (b))
    #define mset(x,v) memset((x),(v),sizeof (x))
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,int> P;
    typedef pair<int,int> pp;
    
    const int maxn=1e5+300;
    const ll inf=1e18;
    int T;
    int N,M;
    int x[maxn],y[maxn],c[maxn],w[maxn];
    int cas;
    const int s=maxn-1;
    ll dis[maxn];
    vector<pp> G[maxn];
    void dij(){
        fill(dis,dis+maxn,inf);
        priority_queue<P,vector<P>,greater<P> > Q;
        dis[s]=0;
        Q.push(P(0,s));
        while(!Q.empty()){
            int u=Q.top().se;
            ll d=Q.top().fs;Q.pop();
            if(d>dis[u]) continue;
            for(int i=0;i<G[u].size();i++){
                int v=G[u][i].fs,d=G[u][i].se;
                if(dis[v]>dis[u]+d){
                    dis[v]=dis[u]+d;
                    Q.push(P(dis[v],v));
                }
            }
        }
    }
    void init(){
        for(int i=0;i<=M;i++){
            G[i].clear();
        }
        G[s].clear();
    }
    void addedge(int from,int to,int d){G[from].pb(pp(to,d));}
    int main(){
        freopen("/home/slyfc/CppFiles/in","r",stdin);
        //freopen("/home/slyfc/CppFiles/out","w",stdout);
        cin>>T;
        while(T--){
            scanf("%d%d",&N,&M);
            init();
            int f=0;
            for(int i=1;i<=N;i++)
                scanf("%d",&x[i]);
            for(int i=1;i<=N;i++)
                scanf("%d",&y[i]);
            for(int i=1;i<=N;i++)
                scanf("%d",&c[i]);
            for(int i=1;i<=M;i++)
                scanf("%d",&w[i]);
            for(int i=1;i<=M;i++)
                if(w[i]==0){
                    addedge(s,i,0);
                }
            for(int i=1;i<=N;i++){
                addedge(y[i],x[i],c[i]);
            }
            dij();
            ll cost=0;
            for(int i=1;i<=M;i++){
                if(w[i]<2) continue;
                if(dis[i]==inf){
                    cost=-1;
                    break;
                }
                cost+=dis[i];
            }
            printf("Case #%d: %lld
    ",++cas,cost);
        }
        return 0;    
    }
    View Code

     1219

    题目:求一个无向图中的一个环路使得路径上的权值异或和最大。

    思路:“任意一个环路都是由某些环路线性组合而成",那么我们从任意点出发求出部分环路的异或和,然后高斯消元,最后再求最大值即可。

    /*
    * @author:  Cwind
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-10)
    #define IINF (1<<29)
    #define LINF (1ll<<49)
    #define INF (1000000300)
    #define FINF (1e9)
    #define clr(x) memset((x),0,sizeof (x))
    #define cp(a,b) memcpy((a),(b),sizeof (b))
    #define mset(x,v) memset((x),(v),sizeof (x))
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,int> P;
    typedef pair<int,int> pp;
    
    const int maxn=5e4+300;
    int T;
    struct EDGE{
        int to;
        ll w;
        EDGE(int to,ull w):to(to),w(w){}
    };
    vector<EDGE> G[maxn];
    int n,m;
    bool vis[maxn];
    ll val[600];
    ll up[500];
    ll xx[maxn];
    void init(){
        for(int i=0;i<=n;i++){
            G[i].clear();
        }
        memset(vis,0,sizeof vis);
        memset(val,0,sizeof val);
        ll x=1;
        up[0]=x;
        for(int i=1;i<63;i++){
            x<<=1;
            up[i]=x;
        }
    }
    void add(ll v){
        if(v==0) return;
        int bit=0;
        for(int i=0;i<63;i++){
            if(v>=up[i]) bit=i;
        }
        for(int i=bit;i>=0;i--){
            if(v==0) break;
            if(v<up[i]) continue;
            if(val[i]==0){
                val[i]=v;
                break;
            }else{
                v=val[i]^v;
            }
        }
    }
    void dfs(int v,ll num){
        vis[v]=1;
        xx[v]=num;
        for(int i=0;i<G[v].size();i++){
            EDGE &e=G[v][i];
            if(!vis[e.to]) dfs(e.to,num^e.w);
            else add(num^e.w^xx[e.to]);
        }
    }
    int cas;
    int main(){
        freopen("/home/slyfc/CppFiles/in","r",stdin);
        //freopen("/home/slyfc/CppFiles/out","w",stdout);
        cin>>T;
        while(T--){
            scanf("%d%d",&n,&m);
            init();
            int s;
            for(int i=0;i<m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                ull c;
                cin>>c;
                G[a].pb(EDGE(b,c));
                G[b].pb(EDGE(a,c));
                s=a;
            }
            dfs(s,0);
            ll ans=0;
            for(int i=63;i>=0;i--)
                ans=max(ans,ans^val[i]);
            printf("Case #%d: %lld
    ",++cas,ans);
        }
        return 0;    
    }
    View Code
  • 相关阅读:
    Locks Set by Different SQL Statements in InnoDB
    InnoDB Record, Gap, and Next-Key Locks
    Ajax上传文件/照片时报错TypeError :Illegal invocation
    自定义函数
    js表格打印自动分页demo
    「译」setState如何知道它该做什么?
    彻底弄懂session,cookie,token
    JS下载文件常用的方式
    node服务端渲染(完整demo)
    马上收藏!史上最全正则表达式合集
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4924271.html
Copyright © 2020-2023  润新知