zoukankan      html  css  js  c++  java
  • Codeforces Round #662 (Div. 2)(A->D(dp))

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

    解析:

    猜的,没看懂题意。

    #include <bits/stdc++.h>
    #include<stdlib.h>
    using namespace std;
    typedef long long ll;
    const int N=100010;
    int a[N],b[N],f[N*2];
    bool c[N*2];
    map<int,int> m;
    int find(int x)
    {
      if(f[x]!=x) f[x]=find(f[x]);
      return f[x];
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            ll n;
            cin>>n;
            cout<<n/2+1<<endl;
        }
    }

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

    题意:

    给出N个长度已给出的木板,接下来进行增加/减少对应长度木板的操作(减少的前提是对应长度存在)

    问是否能组成一个正方形+一个长方形(可为正方形)

    解析:

    记录两个值,出现次数为4的有几个,出现次数为2的有几个。

    出现次数为4,记录后马上清0。

    本解法达到了这么一个目的:

    比如:1  1  1  1  1  1  2  2

    f2=3

    f4=1

    f4中包含了一个f2。

    具体的看注释吧:

    #include<iostream>
    #include<map>
    #include<set>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    int a[maxn];
    int main()
    {
        int n;
        cin>>n;
        int f2=0,f4=0;
        map<int,int>m;
        for(int i=1;i<=n;i++)
        {
            int g;
            cin>>g;
            m[g]++;
            if(m[g]==4)
                f4++,m[g]=0;  
            if(m[g]==2)
                f2++;  //所以f4里包含了一个f2,最后要特殊处理
        }
        int q;
        cin>>q;
        while(q--)
        {
            char ch;
            int h;
            cin>>ch>>h;
            if(ch=='+')
            {
                m[h]++;
                if(m[h]==4)
                    f4++,m[h]=0;
                if(m[h]==2)
                    f2++;    
            }
            else
            {
                m[h]--;  
                if(m[h]==-1)  //-1了,说明这个m[h]之前为0,那么之前就是为4,所以-1后,变成3即可。
                    m[h]=3;
                if(m[h]==3)  //既然变成了3,说明之前为4,那么f4--
                    f4--;
                if(m[h]==1)    //之前为2,所以f2--
                    f2--;
            }
            if(f4>=2||(f4==1&&f2>=3))  //f4中包含了一个f2,所以f2需要多一个才能组成长方形
                cout<<"YES"<<endl;
            else
                cout<<"NO"<<endl;
        }
        
    }

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

    构造+贪心+公式

    题意:

    n个蛋糕,编号对应所属类型。怎么样排序,使得相同类型蛋糕的间隔的最小值最大。求这个值。

    解析:

    很明显,贪心,要想最小值最大,那么同类型之间要尽可能地插入其他类型蛋糕,而且在这些间隔中,要平均地插。

    那么首要起决定性作用的,是出现次数最多的那个。

    比如:

    1  1  1  1  2  3  4

    有:1  2  1  3  1  4  1

    如果出现最多次数的类型有多个:

    1  1  1  1  2  2  2  2  3  4  5  6  7  8

    有:1  2 (3,4)  1  2   (5,6)  1  2 (7,8)  1  2

    既,出现最多的这些类型,每个取一个依次放,做为隔板,其他的平均往里插即可。

    那么根据此,可以得到公式:

    maxx为出现次数最多的次数,num为几个同maxx

    (num-1)+(n-num*maxx)/(maxx-1)

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    #include<map>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int mod=60;
    const int maxn=1e5+7;
    int l[maxn],r[maxn];
    int a[maxn];
    int b[8*maxn];
    int vis[maxn];
    ll c[maxn],d[maxn];
    int pos[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
        //    memset(vis,0,sizeof(vis));
            int maxx=0;
            map<int,int>m;
            for(int i=1;i<=n;i++)
            {
                int x;
                cin>>x;
                m[x]++;
                maxx=max(maxx,m[x]);
            }
            int num=0;
            for(int i=1;i<maxn;i++)
            {
                if(m[i]==maxx)
                {
                    num++;
                }
            }
            cout<<num-1+(n-num*maxx)/(maxx-1)<<endl;
        }
    }

    D:https://codeforces.com/contest/1393/problem/D

    题意:

    问n*m的矩阵中,有多少个如图菱形(单个字符也算)

    解析:参考自:

    https://blog.csdn.net/hzf0701/article/details/107875485?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159696442619724848336941%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=159696442619724848336941&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v28-8-107875485.pc_first_rank_v2_rank_v28&utm_term=Codeforces+Round+%23662&spm=1018.2118.3001.4187

    定义dp[i][j],表示以(i,j)为最底端的菱形的个数

    对于(i-1,j)这个点,已经被(i-2,j)所维护,不必再看。

    以(i,j)为底的菱形,它的扩大取决于标注的另外三个点,能扩多大,又取决于这三个点至少能够延伸多少,所以要对它们取min()

    转移方程:

    dp[i][j]=1;

    dp[i][j]+=min(min(dp[i-1][j-1],dp[i-1][j+1]),dp[i-2][j]);

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<stack>
    #include<map>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int mod=60;
    const int maxn=1e5+7;
    int l[maxn],r[maxn];
    int a[maxn];
    int b[8*maxn];
    int vis[maxn];
    ll c[maxn],d[maxn];
    int pos[maxn];
    const int maxn2=2e3+10;
    char mp[maxn2][maxn2];
    int dp[maxn2][maxn2];
    int main()
    {
        int n,m;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
                cin>>mp[i][j];
        }
        int sum=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                dp[i][j]=1;
                if(i>=2&&j>=1&&j<m-1&&mp[i][j]==mp[i-1][j-1]&&mp[i][j]==mp[i-1][j+1]&&mp[i][j]==mp[i-2][j]&&mp[i][j]==mp[i-1][j])
                {
                    dp[i][j]+=min(min(dp[i-1][j-1],dp[i-1][j+1]),dp[i-2][j]);
                    
                }sum+=dp[i][j];
            //    cout<<dp[i][j]<<' ';
            }
        }
        cout<<sum<<endl;
    }
  • 相关阅读:
    设计模式-适配器模式(09)
    windows电脑使用技巧及常用CMD
    接口调用方法
    矩阵对角线和
    函数基础小结
    文件处理实战之购物车系统
    文件处理小结
    Python进阶实战之三级菜单
    Python进阶小结
    Python深浅拷贝
  • 原文地址:https://www.cnblogs.com/liyexin/p/13461196.html
Copyright © 2011-2022 走看看