ACM-ICPC 2017 南宁赛区现场赛 L,I,H题

L题:

    题目链接:https://nanti.jisuanke.com/t/A1541

   题意:找到最小的n且大于L的数字满足2*m(m+1)=n*(n+1);

   思路:打表找规律,我脑子不够用,没找出来;规律是:ans[i]=ans[i-1]*6-ans[i-2]+2;

              然后再大数模拟下就可以了;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
int a[2005][2005],b[2005];
char c[2000];
int main()
{
    b[0]=1;
    b[1]=2;
    a[0][0]=3;
    a[1][0]=0;
    a[1][1]=2;
    for(int i=2; i<=300; i++)
    {
        for(int j=0; j<b[i-1]; j++)
            a[i][j]=a[i-1][j]*6;
        a[i][0]+=2;
        for(int j=0; j<b[i-2]; j++)
            a[i][j]-=a[i-2][j];
        int v=0;
        for(int j=0; j<b[i-1]; j++)
        {
            if(v==1)
            {
                if(a[i][j]<=0)
                    a[i][j]+=9;
                else
                {
                    a[i][j]--;
                    v=0;
                }
            }
            else
            {
                if(a[i][j]<0)
                {
                    a[i][j]+=10;
                    v=1;
                }
            }
        }
        for(int j=0; j<b[i-1]; j++)
        {
            a[i][j+1]=a[i][j+1]+a[i][j]/10;
            a[i][j]=a[i][j]%10;
        }
        if(a[i][b[i-1]]>0)
            b[i]=b[i-1]+1;
        else
            b[i]=b[i-1];
    }
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",c);
        int n=strlen(c);
        int k=lower_bound(b,b+300,n)-b;
        for(int i=k; i<=300; i++)
        {
            if(b[i]>n)
            {
                for(int j=b[i]-1; j>=0; j--)
                    printf("%d",a[i][j]);
                printf("\n");
                break;
            }
            int v=1;
            for(int j=n-1; j>=0; j--)
            {
                if(a[i][j]>c[n-j-1]-'0')
                    break;
                else if(a[i][j]<c[n-j-1]-'0')
                {
                    v=0;
                    break;
                }
            }
            if(v==1)
            {
                for(int j=b[i]-1; j>=0; j--)
                    printf("%d",a[i][j]);
                printf("\n");
                break;
            }
        }
    }
    return 0;
}

 I题:

       题目链接:https://nanti.jisuanke.com/t/A1538

       题意:有4*4的矩阵,两个人玩游戏,先手从其中任选2*2的矩阵,然后将所选矩阵逆时针转一下,后手从其中任选2*2的矩阵,然后将所选矩阵逆时针转一下,每一轮先手的任                      务是让两人的和最大,后手的任务是让两人的和最小,进行k轮,问k轮两人所选的矩阵的所有加和是多少。

       思路:k不是很大,而且后面的选择不会影响到前面的选择,所以可以dfs回溯求值

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
int inf=99999999;
int a[5][5];
int n;
void L(int x,int y)
{
    int p=a[x][y];
    a[x][y]=a[x][y+1];
    a[x][y+1]=a[x+1][y+1];
    a[x+1][y+1]=a[x+1][y];
    a[x+1][y]=p;
}
void R(int x,int y)
{
    int p=a[x][y];
    a[x][y]=a[x+1][y];
    a[x+1][y]=a[x+1][y+1];
    a[x+1][y+1]=a[x][y+1];
    a[x][y+1]=p;
}
int fun(int x,int y)
{
    return a[x][y]+a[x][y+1]+a[x+1][y]+a[x+1][y+1];
}
int dfs(int x)
{
    if(x==2*n)
    {
        int mi=inf;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
            mi=min(mi,fun(i,j));
        return mi;
    }
    if(x%2==1)
    {
        int ma=0;
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
        {
            L(i,j);
            int ans=fun(i,j)+dfs(x+1);
            R(i,j);
            ma=max(ma,ans);
        }
        return ma;
    }
    int mi=inf;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
    {
        L(i,j);
        int ans=fun(i,j)+dfs(x+1);
        R(i,j);
        mi=min(mi,ans);
    }
    return mi;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=4;i++)
            for(int j=1;j<=4;j++)
            scanf("%d",&a[i][j]);
        printf("%d\n",dfs(1));
    }
}

  

H题:

        题目链接:https://nanti.jisuanke.com/t/A1537

        题意:给出n*m的字符型矩阵,'.'表示不存在细胞,’#‘表示存在。若当前活着的细胞旁边(8联通)存在的活着的细胞数小于2,则当前细胞死亡;

                  若当前活着的细胞旁边存在的活着的细胞数等于2,则当前细胞能够进行到下一次的分裂;

                  若当前细胞(死细胞或活细胞)旁边存在的活着的细胞数等于3,则当前位置的细胞变活;

                 若当前的细胞旁边存在的活着的细胞数大于3,则当前细胞死亡;

        思路:暴力模拟就可以了,每次更新活细胞在哪个范围里,然后暴力就可以了;

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstdlib>
using namespace std;
typedef long long ll;
char cc[10];
int a[800][800],b[800][800];
int fun(int x,int y)
{
    int s=0;
    for(int i=x-1;i<=x+1;i++)
        for(int j=y-1;j<=y+1;j++)
    {
        if(i==x&&j==y)
            continue;
        if(a[i][j]==1)
            s++;
    }
    return s;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        int n,m;
        scanf("%d %d",&n,&m);
        int l=400,r=400+n;
        int ll=400,rr=400+m;
        int l1=l,r1=r;
        int ll1=ll,rr1=rr;
        int ma=0,p=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",cc);
            for(int j=0;j<m;j++)
            {
                if(cc[j]=='#')
                {
                    a[i+400][j+400]=1;
                    b[i+400][j+400]=1;
                    ma++;
                }
            }
        }
        for(int k=1;k<=321;k++)
        {
            int sum=0;
            for(int i=l-1;i<=r+1;i++)
                for(int j=ll-1;j<=rr+1;j++)
            {
                int x=fun(i,j);
                if(x<2||x>3)
                    b[i][j]=0;
                else if(x==3)
                    b[i][j]=1;
                if(b[i][j]==1)
                {
                    sum++;
                    l1=min(l1,i);
                    r1=max(r1,i);
                    ll1=min(ll1,j);
                    rr1=max(rr1,j);
                }

            }
            if(sum>ma)
            {
                ma=sum;
                p=k;
            }
            if(k==321)
               printf("%d %d %d\n",p,ma,sum);
            for(int i=l-1;i<=r+1;i++)
                for(int j=ll-1;j<=rr+1;j++)
                a[i][j]=b[i][j];
            l=l1;
            r=r1;
            ll=ll1;
            rr=rr1;
        }
    }
    return 0;
}

  

posted @ 2019-10-10 22:28  ~zcb  阅读(283)  评论(0编辑  收藏  举报