zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 93 (Rated for Div. 2)(A-D:三维DP)

    A:http://codeforces.com/contest/1398/problem/A

    题意:

    在非递减序列中找非法三角形

    解析:

    刚开始搞了个结构体排序,然后才发现给出的就是非递减。。。

    看1,2,n,如果它三能组成三角形,一定不存在非法。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5e4+20;
    ll a[maxn];
    struct node
    {
        int x;
        int id;
    }st[maxn];
    bool cmp(node a,node b)
    {
        return a.x<b.x;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            for(int i=1;i<=n;i++)
            {
                cin>>a[i];
            }
            int x1=a[1],x2=a[2],x3=a[n];
            if((x1+x2)>x3&&(x3-x1)<x2&&(x3-x2)<x1&&(x2-x1)<x3)
                cout<<"-1"<<endl;
            else
                cout<<"1 2 "<<n<<endl;
        }
    }

    B:http://codeforces.com/contest/1398/problem/B

    题意:

    01字符串。

    操作是每次删除一串连续1,得分为连续1的数目。两人依次操作,求先手的得分。

    解析:

    把所有连续1收集起来,排序,从大到小拿即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5e4+20;
    int a[maxn];
    int b[maxn];
    struct node
    {
        int x;
        int id;
    }st[maxn];
    bool cmp(node a,node b)
    {
        return a.x<b.x;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            string s;
            cin>>s;
            int le=s.length();
            int cnt=0,ok=0,tot=0;
            for(int i=0;i<le;i++)
            {
                if(s[i]=='1')
                {
                    int md=1,k;
                    int ok2=0;
                    if(i<le-1){
                        for(int j=i+1;j<le;j++)
                        {
                            if(s[j]=='1')
                                md++;
                            else
                            {
                                k=j;
                                ok2=1;
                                break;
                            }
                        }
                    }            
                    if(!ok)
                    {
                    //    cnt+=md;
                        ok=1;
                    }
                    else
                        ok=0;
                    b[tot++]=md;    
                    if(!ok2)
                    {
                        break;    
                    }        
                    i=k-1;            
                }
            }
            ok=0;
            cnt=0;
            sort(b,b+tot);
            for(int i=tot-1;i>=0;i--)
            {
                if(!ok)
                    {
                        cnt+=b[i];ok=1;
                    }
                else
                    ok=0;
            }
            cout<<cnt<<endl;
        }
    }

    C:http://codeforces.com/contest/1398/problem/C

    题意:

    求所有好序列的数目。

    好序列:sum[j]-sum[i]==j-i+1

    解析:

    很明显,先把前缀和弄出来。

    有:sumj-sum(i-1)==j-i+1

    考虑把所有数字均-1,那么变成:sumj-sum(i-1)-(j-i+1)=0

    那么就是求:所有区间和为0的区间数。

    n*n很明显行不通。

    如果某个sum出现多次,那么这一次与上一次的区间和就为0,与上上一次的区间和也为0,那么总的可构造的数目就是:cnt+=sum之前出现的数目

    map记录次数,记得初始化mp[0]==0。

    #include<bits/stdc++.h>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+20;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            map<ll,int>m;
            string s;
            cin>>s;
            m[0]++;
            ll sum=0;
            ll cnt=0;
            for(int i=0;i<s.length();i++)
            {
                sum+=s[i]-'1';  //-1
                cnt+=m[sum];
                m[sum]++;
            }
            cout<<cnt<<endl;
        }
    }

    D:http://codeforces.com/contest/1398/problem/D

    题意:

    给定若干个红色,绿色,蓝色的一对长度一样的棍子.问用这些棍子组成的颜色不同的矩形的面积的最大总和是多少.注意不能把两个相同颜色的一对棍子拆成两个分别去用.其次颜色不同指的是在两个集合里选的两对棍子.

    解析:

    考虑贪心,但是写着很麻烦。。

    就看了题解,原来是个三维DP

    定义dp[i][j][k],表示红色用了i个,绿色用了j个,蓝色用了k个的前提下,所获得的最大矩形面积和。

    理解这个转移方程,还是之前的dp思路:选的大还是不选的大?

    #include<bits/stdc++.h>
    #include<map>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const int maxn=2e2+20;
    //const ll inf=0x3f3f3f3f3f3f3f3f;
    int r[maxn],g[maxn],b[maxn];
    ll dp[maxn][maxn][maxn];
    int main()
    {
        int c1,c2,c3;
        cin>>c1>>c2>>c3;
        for(int i=1;i<=c1;i++)    cin>>r[i];sort(r+1,r+1+c1);
        for(int i=1;i<=c2;i++)    cin>>g[i];sort(g+1,g+1+c2);
        for(int i=1;i<=c3;i++)    cin>>b[i];sort(b+1,b+1+c3);
        ll maxx=0;
        for(int i=0;i<=c1;i++)
        {
            for(int j=0;j<=c2;j++)
            {
                for(int k=0;k<=c3;k++)
                {
                    if(i&&j)    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+r[i]*g[j]);
                    if(i&&k)    dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+r[i]*b[k]);
                    if(j&&k)    dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+g[j]*b[k]);
                    maxx=max(maxx,dp[i][j][k]);
                }
            }
        }
        cout<<maxx<<endl;
    }
  • 相关阅读:
    SpringBoot+SpringCloud
    bootstrap-thymeleaf-分页
    排序-Java
    native2ascii运用
    标准W3C盒子模型和IE盒子模型
    在既定状态下截图
    java.util.zip.ZipException: error in opening zip file
    安装 haproxy
    mysql集群
    最简redis集群配置
  • 原文地址:https://www.cnblogs.com/liyexin/p/13509582.html
Copyright © 2011-2022 走看看