zoukankan      html  css  js  c++  java
  • 叉姐的魔法训练(第八课)---- 幽默术

    --------------

    一 MSTDP

    POJ 3538 Domestic Networks

    有n个点m条边,和5型6型两种线,每米花费p5、p6,各有q5、q6米。

    每条边要么用5型连接要么用6型,或不连接。

    求将n个点连接的最小花费。与最小花费的方案。

    首先求出最小生成树。

    在对树上的边进行dp。

    f[ i ][ j ] 表示 前i条路用5型j米的最小花费。

    f[i][j]=f[i-1][j]+c*p6 (第i条路不使用5型)
    f[i][j]=f[i-1][j-c]+c*p5 (第i条路使用5型)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #define rst(x) memset(x,0,sizeof(x))
    #define clr(x,a) memset(x,a,sizeof(x))
    #define sz(x) int(x.size())
    using namespace std;
    
    const int maxn=1111;
    const int maxm=11111;
    const int INF=0x3f3f3f3f;
    int n,m;
    
    struct Edge{
        int u;
        int v;
        int w;
        int id;
        bool operator<(const Edge& rhs) const{
            return w<rhs.w;
        }
    }road[maxm];
    struct Node{
        int w;
        int id;
        Node(int w,int id){
            this->w=w;
            this->id=id;
        }
        bool operator<(const Node& rhs) const{
            return id<rhs.id;
        }
    };
    
    int pa[maxn];
    void makeSet(int n){
        for (int i=0;i<=n;i++) pa[i]=i;
    }
    int findSet(int x){
        if (x!=pa[x]) pa[x]=findSet(pa[x]);
        return pa[x];
    }
    void unionSet(int x,int y){
        x=findSet(x);
        y=findSet(y);
        if (x!=y) pa[x]=y;
    }
    
    int p5,q5,p6,q6;
    int sum,num;
    vector<Node>a;
    
    int f[1005][10005];
    int path[1005][10005];
    
    void dfs(int cnt,int y){
        if (!cnt) return;
        if (path[cnt][y]!=y){
            dfs(cnt-1,path[cnt][y]);
            printf("%d 5
    ",a[cnt-1].id);
        }
        else{
            dfs(cnt-1,y);
            printf("%d 6
    ",a[cnt-1].id);
        }
    }
    
    int main()
    {
        while (~scanf("%d%d",&n,&m)){
            makeSet(n);
            a.clear();
            for (int i=0;i<m;i++){
                scanf("%d%d%d",&road[i].u,&road[i].v,&road[i].w);
                road[i].id=i+1;
            }
            scanf("%d%d%d%d",&p5,&q5,&p6,&q6);
            sort(road,road+m);
            sum=0;
            for (int i=0;i<m;i++){
                int u=road[i].u;
                int v=road[i].v;
                int w=road[i].w;
                if (findSet(u)!=findSet(v)){
                    unionSet(u,v);
                    a.push_back(Node(road[i].w,road[i].id));
                    sum+=w;
                }
            }
            if (sz(a)!=n-1||sum>q5+q6){
                printf("Impossible
    ");
                continue;
            }
            sort(a.begin(),a.end());
            memset(f,0x3f,sizeof(f));
            int total=0;
            f[0][0]=0;
            for (int i=1;i<=sz(a);i++){
                total+=a[i-1].w;
                int c=a[i-1].w;
                for (int j=q5;j>=0;j--){
                    if (total-j<=q6&&f[i-1][j]!=INF&&f[i-1][j]+c*p6<f[i][j]){
                        f[i][j]=f[i-1][j]+c*p6;
                        path[i][j]=j;
                    }
                    if (j>=c&&f[i-1][j-c]!=INF&&f[i-1][j-c]+c*p5<f[i][j]){
                        f[i][j]=f[i-1][j-c]+c*p5;
                        path[i][j]=j-c;
                    }
                }
            }
            int ans=INF,y=-1;
            for (int i=0;i<=q5;i++){
                if (ans>f[sz(a)][i]){
                    ans=f[sz(a)][i];
                    y=i;
                }
            }
            if (ans==INF) printf("Impossible
    ");
            else{
                printf("%d
    ",ans);
                dfs(sz(a),y);
            }
        }
        return 0;
    }
    

    -------------------------------

    二 构造方案

    POJ 3566 Building for UN

    题解摘自网络:
    题目大意:要建新的联合国总部,每个国家都有若干相连的房间,请你设计一种方案,使每个国家的都有房子能够与其他国家的某个房间相邻,使这两个国家可以讨论秘密国事。用字母表示这些国家。
    下面这样的方案就能满足题目的要求,而且能够满足各种n。例如,n=4:
    ABCD
    AAAA

    ABCD
    BBBB

    ABCD
    CCCC

    ABCD
    DDDD

    相当于每个国家在每层楼各有一个办公室,从纵向看,一个竖条都是一个国家。每个国家在某层都有一个阳台,通向其他国家的办公室。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int maxn=1111;
    int a[2][maxn];
    char list[maxn];
    int main()
    {
        int n,h,w,l;
        for(int i=0;i<26;i++) list[i]='A'+i;
        for(int i=0;i<26;i++) list[26+i]='a'+i;
        scanf("%d",&n);
        h=n,w=n,l=2;
        printf("%d %d %d
    ",h,w,l);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++) printf("%c",list[i]);
            printf("
    ");
            for(int j=0;j<n;j++) printf("%c",list[j]);
            if (i!=n-1) printf("
    
    ");
            else printf("
    ");
        }
        return 0;
    }
    


    -------------------------------

    三 SG分解

    POJ 3537 Crosses and Crosses

    摘自学姐博客:在第I个位置放一个X,即可分为两个子游戏,I-3和n-I-2

    #include<iostream>
    #include<cstdlib>
    #include<stdio.h>
    #include<memory.h>
    using namespace std;
    int sg[2100];
    int dfs(int n)
    {
        if(n<0) return 0;//n<0
        if(sg[n]>=0) return sg[n];
        bool g[2001]={0};
        for(int i=1;i<=n;i++)
        {
            int t=dfs(i-3)^dfs(n-i-2);
            g[t]=1;
        }
        for(int i=0;;i++)
        if(g[i]==0) return sg[n]=i;
    }
    int main()
    {
        memset(sg,-1,sizeof(sg));
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            if(dfs(n)) puts("1");
            else puts("2");
        }
    }
    


    -------------------------------

  • 相关阅读:
    Ace教你一步一步做Android新闻客户端(三) JSON数据解析
    阿冰教你一步一步做Android新闻客户端(二)两种异步线程加载图片的方法
    Android Studio快捷键
    Ace教你一步一步做Android新闻客户端(一)
    Android退出所有Activity最优雅的方式
    Android热门网络框架Volley详解
    Android必学之AsyncTask
    learning scasl notes
    learning armbian steps(11) ----- armbian 源码分析(六)
    am335x system upgrade set/get current cpufreq(二十一)
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681560.html
Copyright © 2011-2022 走看看