2018年全国多校算法寒假训练营练习比赛(第二场)A B D E F G H

吐泡泡

自左到右,循环修改。

  1. 代码:

#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
using namespace std;
int v[200];
int main()
{
    char s[150];
    while(~scanf("%s",s))
    {int len,cnt;
        len=strlen(s);
        memset(v,0,sizeof(v));
        for(int i=0;i<len;i++)v[i]=1;
        while(1)
        {
        char qian='q';
        int qia=0;
        for(int i=0;i<len;i++)
        {
            if(v[i])
            {
            if(qian==s[i]&&s[i]=='o'){s[i]='O';v[qia]=0;v[i]=1;break;}
            else if(qian==s[i]&&s[i]=='O'){v[qia]=0;v[i]=0;break;}
            qian=s[i];
            qia=i;
            }
        }
        int l=1;
        qian='q';
        qia=0;
        for(int i=0;i<len;i++)
        {
            if(v[i])
            {
                if(qian==s[i])l=0;
                qian=s[i];
                qia=i;
            }
        }
        if(l)break;
        }
        for(int i=0;i<len;i++)
        {
            if(v[i]){cout<<s[i];}
        }
        cout<<endl;



    }
    return 0;
} 
TaoTao要吃鸡 

01背包扩容

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[110][220][2];
int main()
{
    int n,m,h;
    int q,w;
    while(scanf("%d",&n)&&n)
    {
        scanf("%d%d",&m,&h);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&q,&w);
            for(int j=0;j<=m+h;j++)
            {
                dp[i][j][0]=dp[i-1][j][0];
                if(j+q<=m+h)dp[i][j][0]=max(dp[i][j][0],dp[i-1][j+q][0]+w);
                ans=max(ans,dp[i][j][0]);
            }
            if(h)
            {
                for(int j=1;j<=m+h;j++)
                {
                   dp[i][j][1]=dp[i-1][j][1];
                   dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][0]+w);
                   if(j+q<=m+h)dp[i][j][1]=max(dp[i][j][1],dp[i-1][j+q][1]+w);
                   ans=max(ans,dp[i][j][1]);
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
D YB要打炉石

最长上升子序列

代码:

#include <iostream>

using namespace std;

int main()
{int n,ma=0,sum=0;
int a[1001]={0},b[1001]={0};
b[1]=1;
cin>>n;
for(int i=1;i<=n;i++)
{cin>>a[i];}
for(int i=2;i<=n;i++)
{
ma=0;
for(int t=1;t<i;t++)
{if(a[i]>=a[t]){
if(b[t]>ma){ma=b[t];}

}

     }
     b[i]=ma+1;
}

for(int i=1;i<=n;i++)
{if(sum<b[i])sum=b[i];
}
if(sum>=30)cout<<"yes"<<endl;
else cout<<"no"<<endl;
    return 0;
}
E 小G有一个大树

树形dp求树的重心

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

int n;
int d[50005];
int dp[50005];
int head[50005];
int minshu;
int ans;
struct shu
{
    int v;
    int next;
}tr[100005];
void add(int q,int w)
{
    tr[ans].v=w;
    tr[ans].next=head[q];
    head[q]=ans++;

}
void dfs(int x,int pa)
{
    d[x]=1;
    int maxshu=-1000000;
    for(int i=head[x];i!=-1;i=tr[i].next)
    {
        int son=tr[i].v;
        if(son!=pa)
        {
            dfs(son,x);
            d[x]+=d[son];
            maxshu=max(maxshu,d[son]);
        }
    }
    dp[x]=max(maxshu,n-d[x]);
    minshu=min(dp[x],minshu);

}
int main()
{

    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
         memset(d,0,sizeof(d));
          memset(head,-1,sizeof(head));
        ans=0;
        for(int i=1;i<n;i++)
        {
            int q,w;
            scanf("%d%d",&q,&w);
            add(q,w);
            add(w,q);
        }

    minshu=10000000;
    dfs(1,-1);
    for(int i=1;i<=n;i++)
    {
        if(dp[i]==minshu)
        {
            printf("%d ",i);
        }
    }
    cout<<minshu<<endl;
    
    }
    return 0;
}
F 德玛西亚万岁

数位dp,怎么种小麦的原题

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define mod 100000000
#define ma 14
int dp[ma][1<<ma],st[ma];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        memset(st,0,sizeof(st));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<m;j++)
            {
                int a;
                scanf("%d",&a);
                st[i]|=a<<j;//记录每一行的状态
            }

        }
        memset(dp,0,sizeof(dp));
        dp[0][0]=1;
        for(int i=1;i<=n;i++)//枚举行
        {
            for(int j=0;j<(1<<m);j++)//枚举本行状态
            {
               if((j&st[i])==j&&((j&(j>>1))==0))//条件 :该状态被本行状态包含  该行每个玉米都间隔1以上
               {
                   for(int k=0;k<(1<<m);k++)//枚举上一行状态
                   {
                       if((j&k)==0)//两行的状态没有接触的
                       {
                           dp[i][j]=(dp[i-1][k]+dp[i][j])%mod;
                       }
                   }
               }
            }

        }
        int ans=0;
        for(int i=0;i<(1<<m);i++)
        {
            ans=(dp[n][i]+ans)%mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}
G 送分了QAQ
状态压缩dp,类似求包含49 的题。

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int a[30];
long long dp[30][20][15];

long long sove(int pos,int qian,int bb,int limit)
{
    if(pos==-1)return bb;
    if(!limit&&dp[pos][qian][bb]!=-1)return dp[pos][qian][bb];
    long long sum=0;
    int end=limit?a[pos]:9;
    for(int i=0;i<=end;i++)
    {
        if((qian==3&&i==8)||i==4)sum+=sove(pos-1,i,1,limit&&(i==a[pos]));
        else sum+=sove(pos-1,i,bb,limit&&(i==a[pos]));
    }
    if(!limit)dp[pos][qian][bb]=sum;
    return sum;
}

long long go(long long x)
{
    int pos=0;
    while(x)
    {
        a[pos++]=x%10;
        x/=10;
    }

    return sove(pos-1,0,0,1);
}
int main()
{
    int n,m;

    while(~scanf("%d%d",&n,&m)&&(n+m))
    {

        memset(dp,-1,sizeof(dp));
        memset(a,0,sizeof(a));

        printf("%lld\n",go(m)-go(n-1));
    }
    return 0;
}
H 了断局

递推一个数列,类似斐波那契数列。

代码:

#include <iostream>
#include <cstdio>
using namespace std;
long long a[60];
void q()
{
    a[1]=0;
    a[2]=1;
    a[3]=1;
    for(int i=4;i<=55;i++)
    {
        a[i]=a[i-1]+a[i-2]+a[i-3];
    }
}
int main()
{
    int n;
    q();
    while(~scanf("%d",&n))
    {
        printf("%lld\n",a[n]);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值