zoukankan      html  css  js  c++  java
  • Codeforces Round #533 (Div. 2)

    A. Salem and Sticks

    由于长度很小,所以直接暴力枚举最后的长度即可,取最小值即可。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=10010;
    int a[1100],n;
    int cost,ans;
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        int co=inf,ans=0;
        for(int i=1;i<=100;i++)
        {
            int tep=0;
            for(int j=1;j<=n;j++)
            {
                if(a[j]>=i+1)tep+=a[j]-1-i;
                else if(a[j]<=i-1)tep+=i-1-a[j];
            }
            if(tep<co){
                co=tep,ans=i;
            }
        }
        
        cout<<ans<<" "<<co<<endl;
    }
    View Code

    B - Zuhair and Strings

    用数组模拟栈,水题,要读清题意。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=20010;
    int n;
    int a[200],ans[200];
    int main(){
        string s;
        int k;
        cin>>n>>k;
        cin>>s;
        for(int i=0;i<n;i++)
        {
            if(a[s[i]]==0){
                CLR(a,0);
                
            }
            a[s[i]]++;
            ans[s[i]]+=a[s[i]]/k;
            a[s[i]]%=k;
        }
        int maxx=0;
        for(int i='a';i<='z';i++)
        {
            maxx=max(maxx,ans[i]);
        }
        cout<<maxx<<endl;
    }
    View Code

    C. Ayoub and Lost Array

    先预处理出 [ l , r ] ,所有除以3余0,余1,余2的个数,然后dp[ s ][ i ]表示到第 i 位,和的余数为 s 的方案个数,dp式子也很好列,看代码就行了。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a));
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int maxn=200010;
    ll p=1e9+7;
    ll dp[3][maxn],l,r;
    int n;
    ll a[3];
    int main(){
        cin>>n>>l>>r;
        while(l<=r&&(r-l+1)%3!=0){
            a[l%3]++;
            l++;
        }
    
        a[0]+=(r-l+1)/3;
        a[1]+=(r-l+1)/3;
        a[2]+=(r-l+1)/3;
        dp[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            dp[0][i]=((dp[0][i-1]*a[0]%p)+(dp[1][i-1]*a[2]%p)+(dp[2][i-1]*a[1]%p))%p;
            dp[1][i]=((dp[0][i-1]*a[1]%p)+(dp[1][i-1]*a[0]%p)+(dp[2][i-1]*a[2]%p))%p;
            dp[2][i]=((dp[0][i-1]*a[2]%p)+(dp[1][i-1]*a[1]%p)+(dp[2][i-1]*a[0]%p))%p;
        }
        printf("%lld
    ",dp[0][n]);
    }
    View Code

    D. Kilani and the Game

    这个题意看的我自闭,看别人的题解才知道自己读错题了,还好打的不是现场的,不然又要掉分了。

    题目的意思是有p种人,对于每个人,他可以走到距离 s 范围内的所有格子,而且是可以分身的,走过的地方全部被这个人污染(造起堡垒),然后问各种人污染了几个格子。

    如果只有一种人的话,这个bfs只需要处理那些已经走过的区域的最外围就可以了,因为里面那些被包围的肯定没有外围的走的远,最外围的方块就是那些用光了步数才走到的格子,所以这里需要一个bfs。

    现在有很多人,并且要依次执行,所以每种人都要用一个队列bord来保存最外围的格子,然后对一种人进行bfs的时候,把这个队列里的所有元素全部倒入主要的bfs队列q,然后对q进行bfs,把步数用光的那些格子塞回bord。

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1010;
    int n,m,p;
    int vis[maxn][maxn];
    int ans[20],s[20];
    char mp[maxn][maxn];
    int fx[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    struct node{
        int x,y,step;
    };
    queue<node >q;
    queue<node >bord[10];
    bool check(int x,int y){
        if(x<1||x>n||y<1||y>m)return false;
        if(mp[x][y]=='#')return false;
        if(vis[x][y]>0)return false;
        return true;
    }
    void bfs(int id)
    {
        node st,ne;
        while(!q.empty()){
            st=q.front();
            q.pop();
            if(st.step==0){
                bord[id].push({st.x,st.y,s[id]});
                continue;
            }
            for(int i=0;i<4;i++)
            {
                ne=st;
                ne.step--;
                ne.x+=fx[i][0],ne.y+=fx[i][1];
                
                if(check(ne.x,ne.y)){
                    vis[ne.x][ne.y]=id;
                    q.push(ne);
                    
                }
            }
        }
    }
    int expend(int id){
        while(!q.empty())q.pop();
        while(!bord[id].empty()){
            q.push(bord[id].front());
            bord[id].pop();
        }
        bfs(id);
        return !bord[id].empty();
    }
    int main(){
        cin>>n>>m>>p;
        for(int i=1;i<=p;i++)scanf("%d",&s[i]);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",mp[i]+1);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                int id=mp[i][j]-'0';
                if(id>0&&id<=9)
                {
                    bord[id].push({i,j,s[id]});
                    vis[i][j]=id;
                }
            }
        }
        int isok=1;
        while(isok)
        {
            isok=0;
            for(int i=1;i<=p;i++)
            {
                isok|=expend(i);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                ans[vis[i][j]]++;
            }
        }
        for(int i=1;i<=p;i++)
        {
            printf("%d%c",ans[i],i<p?' ':'
    ');
        }
    } 
    View Code

    E. Helping Hiasat

    可以发现一个性质,就是一个1后面连着的所有人名,必定不能同时开心,也就是这些人直接存在一些反边,对于这40个人来说,我们如果枚举240次,然后把这种反边的关系处理掉,就可以得到答案了。

    我们发现,其实这是一个最大独立集的题目,理论上用这种枚举的方式可以过,但是显然时间复杂度太高了,于是我们把人折半,对两部分分别处理,这样的时间复杂度就降为了220*k,k是处理边的常数,虽然有点大,但是有非常多的情况是不会迭代的,所以能过。

    对于一个独立子集要怎么做呢,就是要先预处理出所有边的信息,我们先把所有路设为1,然后把那些断掉的路设为0,用状压dp的写法来搞。

    两个独立子集思想也是这样,具体看代码,简单易懂.jpg

    #include<bits/stdc++.h>
    #define CLR(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    map<string,int>id;
    bool mp[50][50],vis[maxn];
    int cnt,f[1<<21],g[1<<21];
    int n,m,op,s1,s2;
    int sta[maxn],top;
    string s;
    void init(){
        cnt=0;
        CLR(f,0),CLR(g,0);
        CLR(mp,1);
    }
    void buildGraph(){
            while(n--)
            {
                scanf("%d",&op);
                if(op==1){
                    
                    for(int i=1;i<top;i++)
                    {
                        for(int j=i+1;j<=top;j++)
                        {
                            mp[sta[i]][sta[j]]=mp[sta[j]][sta[i]]=0;
                        }
                    }
                    top=0;
                    CLR(vis,0);
                }else{
                    cin>>s;
                    if(!id.count(s))id[s]=cnt++;
                    if(!vis[id[s]]){
                        vis[id[s]]=1;
                        sta[++top]=id[s];
                    }
                }
            }
            for(int i=1;i<top;i++)
            {
                for(int j=i+1;j<=top;j++)
                {
                    mp[sta[i]][sta[j]]=mp[sta[j]][sta[i]]=0;
                }
            }
            top=0;
            CLR(vis,0);
    }
    int main(){
        while(cin>>n>>m)
        {
            init();
            buildGraph();
            s1=m/2,s2=m-s1;
            for(int i=0;i<s1;i++)f[1<<i]=1;
            
            for(int i=0;i<s2;i++)g[1<<i]=1;
            
            for(int i=0;i<(1<<s1);i++)
            {
                for(int j=0;j<s1;j++)
                {
                    if(i&(1<<j))continue;
                    int flag=1;
                    for(int k=0;k<s1;k++)
                    {
                        if(i&(1<<k)){
                            flag&=mp[j][k];
                        }
                    }
                    f[i|(1<<j)]=max(f[i|(1<<j)],f[i]+flag);
                }
            }
            for(int i=0;i<(1<<s2);i++)
            {
                for(int j=0;j<s2;j++)
                {
                    if(i&(1<<j))continue;
                    int flag=1;
                    for(int k=0;k<s2;k++)
                    {
                        if(i&(1<<k)){
                            flag&=mp[j+s1][k+s1];
                        }
                    }
                    g[i|(1<<j)]=max(g[i|(1<<j)],g[i]+flag);
                }
            }
            int ans=0;
            for(int i=0;i<(1<<s1);i++)
            {
                int s3=(1<<s2)-1;
                for(int j=0;j<s1;j++)
                {
                    if(!(i&(1<<j)))continue;
                    for(int k=0;k<s2;k++)
                    {
                        if(!(s3&(1<<k)))continue;
                        if(mp[j][k+s1]==0){
                            s3^=(1<<k);
                        }
                    }
                }
                ans=max(ans,f[i]+g[s3]);
            }
            printf("%d
    ",ans);
            
        }
    }
    View Code
  • 相关阅读:
    为什么学微信小程序开发
    mac 上配置sublime text3插件
    获取元素的宽度和高度
    移动端页面SEO优化需要注意的10个要点
    gulp详细入门教程
    HTTP协议详解
    深入了解 Flexbox 伸缩盒模型
    移动前端之viewport
    如何设置“用eclipse开发时自动在顶端产生import”?
    认识 java JVM虚拟机选项 Xms Xmx PermSize MaxPermSize 区别
  • 原文地址:https://www.cnblogs.com/mountaink/p/10326198.html
Copyright © 2011-2022 走看看