zoukankan      html  css  js  c++  java
  • 11.13的一套题

    题目名称 笔记 括号 城堡

    可执行文件名 note brackets castle

    输入文件名 note.in brackets.in castle.in

    输出文件名 note.in brackets.out castle.in

    每个测试点时限 1 秒 1 秒 1 秒

    内存限制 512MB 512MB 512MB

    测试点数目 20 20 10

    每个测试点分值 5 5 10

    是否有部分分 否 否 否

    题目类型 传统型 传统型 传统型

     


    笔记
    【问题描述】

    给定一个长度为m的序列a,下标编号为1~m。序列的每个元素都是1~n的 整数。定义序列的代价为

                  

     

     你现在可以选择两个数x和y,并将序列a中所有的x改成y。 x可以与y相等。 请求出序列最小可能的代价。
    【输入格式】

    输入第一行包含两个整数n和m。

    第二行包含m个空格分隔的整数,代表序 列a。

    【输出格式】

    输出一行,包含一个整数,代表序列最小的代价。
    【样例输入 1】
    4 6
    1 2 3 4 3 2
    【样例输出 1】
    3
    【样例输入 2】
    10 5
    9 4 3 8 8
    【样例输出 1】
    6
    【样例解释】

    样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。
    【数据规模和约定】

    对于30%的数据, n, m ≤ 100。

    对于60%的数据, n, m ≤ 2000。

    对于100%的数据, 1 ≤ n, m ≤ 100,000。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #define LL long long
    #define maxn 100010
    using namespace std;
    LL n,m,ans,mx;
    LL a[maxn];
    vector<LL>f[maxn];
    LL init()
    {
        LL x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    LL Abs(LL x)
    {
        return x>=0 ? x: -x;
    }
    LL Max(LL x,LL y)
    {
        return x>=y ? x: y;
    }
    int main()
    {
        freopen("note.in","r",stdin);
        freopen("note.out","w",stdout);
        n=init();m=init();
        for(LL i=1;i<=m;i++)a[i]=init();
        for(LL i=1;i<m;i++)ans+=Abs(a[i+1]-a[i]);
        for(LL i=1;i<=m;i++)
        {
            if(i>1&&a[i-1]!=a[i])f[a[i]].push_back(a[i-1]);
            if(i<m&&a[i+1]!=a[i])f[a[i]].push_back(a[i+1]);
        }
        for(LL i=1;i<=n;i++)
        {
            if(f[i].size()==0)continue;
            sort(f[i].begin(),f[i].end());
            LL sum=0,tot=0,mid=f[i].size()/2;
            for(LL j=0;j<f[i].size();j++)
            {
                sum+=Abs(f[i][j]-i);
                tot+=Abs(f[i][j]-f[i][mid]);
            }
            mx=Max(mx,sum-tot);
        }
        cout<<ans-mx<<endl;
        return 0;
    }

    括号
    【问题描述】

    有一个长度为n的括号序列,以及k种不同的括号。序列的每个位置上是哪 种括号是随机的,并且已知每个位置上出现每种左右括号的概率。求整个序列是 一个合法的括号序列的概率。 我们如下定义合法括号序列:

    * 空序列是合法括号序列;
    * 如果A是合法括号序列,那么lAr是合法括号序列,当且仅当l和r是同种 的左右括号;

    * 如果A和B是合法括号序列,那么AB是合法括号序列。
    【输入格式】

    输入第一行包含两个整数n和k。

    接下来的输入分为n组,每组k行。

    第i组第j行包含两个实数l[i, j]和r[i, j],分别代表第i个位置上是第j类的左括号和右括号 的概率。

    【输出格式】

    输出一行,包含一个实数,代表序列是合法括号序列的概率。

    建议保留至少 5 位小数输出。只有当你的输出与标准答案之间的绝对误差不超过10−5时,才会 被判为正确。
    【样例输入 1】
    2 1
    1.00000 0.00000
    0.00000 1.00000
    【样例输出 1】
    1.00000
    【样例输入 2】
    4 1
    0.50000 0.50000
    1.00000 0.00000
    0.00000 1.00000
    0.50000 0.50000
    【样例输出 2】
    0.25000
    【数据规模和约定】

    对于20%的数据, n ≤ 50, k = 1,所有位置的概率非 0 即 1。

    另外有 30%的数据, n ≤ 34, k = 1, 前 10 个和后 10 个位置的所有概率都 是 0.5,中间剩余位置的概率非 0 即 1。

    对于80%的数据, n, k ≤ 50。

    对于100%的数据, 1 ≤ n ≤ 200, 1 ≤ k ≤ 50。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 210
    using namespace std;
    int n,w;
    double l[maxn][maxn],r[maxn][maxn];
    double dp[maxn][maxn],f[maxn][maxn],Dp[maxn][maxn];
    int main()
    {
        freopen("brackets.in","r",stdin);
        freopen("brackets.out","w",stdout);
        scanf("%d%d",&n,&w);
        for(int i=1;i<=n;i++)
          for(int j=1;j<=w;j++)
            scanf("%lf%lf",&l[i][j],&r[i][j]);
        for(int i=1;i<=n;i++)
          for(int j=i+1;j<=n;j++)
            for(int k=1;k<=w;k++)
              f[i][j]+=l[i][k]*r[j][k];
        for(int i=n;i>=1;i--)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(i+1>j-1) Dp[i][j]=f[i][j],dp[i][j]+=f[i][j];
                else Dp[i][j]=dp[i+1][j-1]*f[i][j],dp[i][j]+=Dp[i][j];
                for(int k=i+1;k<j;k++)dp[i][j]+=Dp[i][k]*dp[k+1][j];
            }
        }
        printf("%f",dp[1][n]);
        return 0;
    }

    城堡
    【问题描述】

    给定一张N个点M条边的无向连通图,每条边有边权。我们需要从M条边中 选出N − 1条,构成一棵树。记原图中从 1 号点到每个节点的最短路径长度为Di, 树中从 1 号点到每个节点的最短路径长度为Si,构出的树应当满足对于任意节点i,都有Di= Si。 请你求出选出N− 1条边的方案数。

    【输入格式】

    输入的第一行包含两个整数N和M。

    接下来N行,每行包含三个整数u、 v和w,描述一条连接节点u和v且边权为w的边。

    【输出格式】

    输出一行,包含一个整数,代表方案数对231 − 1取模得到的结果。
    【样例输入】
    3 3
    1 2 2
    1 3 1
    2 3 1
    【样例输出】
    2
    【数据规模和约定】

    对于30%的数据, 2 ≤ N≤ 5, M ≤ 10。

    对于50%的数据, 满足条件的方案数不超过 10000。

    对于100%的数据, 2≤ N ≤ 1000, N − 1 ≤ M ≤ N(N-1)/2 , 1 ≤ w ≤ 100。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define LL long long
    #define inf 100000000
    #define mod 2147483647
    #define maxx 1010
    #define maxn 2000010
    using namespace std;
    LL n,m,topt,ans=1;
    LL first[maxx],f[maxx],dis[maxx],c[maxx];
    struct edge
    {
        LL from,to,val,next;
    }e[maxn*2];
    queue<LL>q;
    LL init()
    {
        LL x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    void add(LL x,LL y,LL z)
    {
        topt++;
        e[topt].from=x;
        e[topt].to=y;
        e[topt].val=z;
        e[topt].next=first[x];
        first[x]=topt;
    }
    void spfa()
    {
        for(LL i=1;i<=n;i++)dis[i]=inf,f[i]=0;
        dis[1]=0;f[1]=1;q.push(1);
        while(!q.empty())
        {
            LL now=q.front();q.pop();f[now]=0;
            for(LL i=first[now];i;i=e[i].next)
            {
                LL to=e[i].to;
                if(dis[to]>dis[now]+e[i].val)
                {
                    dis[to]=dis[now]+e[i].val;
                    if(!f[to])f[to]=1,q.push(to);
                }
            }
        }
    }
    int main()
    {
        freopen("castle.in","r",stdin);
        freopen("castle.out","w",stdout);
        n=init();m=init();
        for(LL i=1;i<=m;i++)
        {
            LL x,y,z;
            x=init();y=init();z=init();
            add(x,y,z);add(y,x,z);
        }
        spfa();
        for(LL i=1;i<=topt;i++)
        {
            LL x=e[i].from;LL y=e[i].to;
            if(dis[x]+e[i].val==dis[y])c[y]++;
        }
        for(LL i=2;i<=n;i++)
          ans=ans*c[i],ans%=mod;
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    C&Pointer求解wc问题
    软件测试作业2
    第六周小组作业
    WordCount改进 小组项目
    WordCount
    我的“游戏”人生
    软件测试第6周小组作业
    软件测试第4周小组作业:WordCount优化
    软件测试第二周个人作业:WordCount
    MVC模式下基于SSH三大框架的java web项目excel表格的导出(不依赖另外的jar包)
  • 原文地址:https://www.cnblogs.com/dingmenghao/p/6063192.html
Copyright © 2011-2022 走看看