2013 Multi-University Training Contest 8

11 篇文章 0 订阅

1003 Mine

简单sg的博弈题,我们走入了nim博弈的误区,后来发现改了三四个字符就过了。。。。我只能说我是sbsbsbsbsbsb。。。判奇偶啊。。。

#pragma comment(linker,"/STACK:102400000,102400000")//用的是dfs搜索,写得挫,不加上这个且用C++交就跪了。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
#define N 9973
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
int n,m,k;
int sum[1005][1005];
int used[1005][1005];
int s[1000005];
int shu,shuk,ans;
int dx[9]={-1,-1,-1,0,0,1,1,1};
int dy[9]={-1,0,1,-1,1,-1,0,1};
void dfs(int x,int y)//用的就是施教主写的
{//这里的目的就是求空白部分周围的数字块数量
    int i;
    used[x][y]=1;
    for(i=0;i<8;i++)
    {
        if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<m)
        {
            if(used[x+dx[i]][y+dy[i]]==0&&sum[x+dx[i]][y+dy[i]]==0)
            {
                dfs(x+dx[i],y+dy[i]);
            }
        }
    }
    for(i=0; i<8; i++)
    {
        if(x+dx[i]>=0&&x+dx[i]<n&&y+dy[i]>=0&&y+dy[i]<m)
        {
            if(used[x+dx[i]][y+dy[i]]==0&&sum[x+dx[i]][y+dy[i]]>0)
            {
                used[x+dx[i]][y+dy[i]]=1;
                shuk++;
            }
        }
    }
}
int main()
{
    int t,cas,i,j,a,b;
    while(scanf("%d",&t)!=EOF)
    {
        cas=0;
        while(t--)
        {
            cas++;
            RD(n);
            RD(m);
            RD(k);
            for(i=0; i<n; i++)
            {
                for(j=0; j<m; j++)
                {
                    sum[i][j]=0;
                    used[i][j]=0;
                }
            }
            for(i=0; i<k; i++)
            {
                RD(a);
                RD(b);
                for(j=0; j<8; j++)
                {
                    if(a+dx[j]>=0&&a+dx[j]<n&&b+dy[j]>=0&&b+dy[j]<m)
                    {
                        sum[a+dx[j]][b+dy[j]]++;
                    }
                }
                used[a][b]=1;
            }
            shu=0;
            for(i=0; i<n; i++)
            {
                for(j=0; j<m;j++)
                {
                    if(used[i][j]==0)
                    {
                        if(sum[i][j]==0)//判奇偶,如果为奇数算作两块,偶数为一块
                        {
                            shuk=0;
                            dfs(i,j);
                            s[shu]=shuk%2+1;//就这里改了一下就AC了,哭啊
                            shu++;
                        }
                    }
                }
            }
            for(i=0; i<n; i++)
            {
                for(j=0; j<m; j++)
                {
                    if(used[i][j]==0)//其它单独数字块各为1块
                    {
                        s[shu]=1;
                        shu++;
                    }
                }
            }
            ans=0;
            for(i=0;i<shu;i++)
            {
                ans^=s[i];//异或一下就行了
            }
            printf("Case #%d: ",cas);
            if(ans!=0)
            {
                printf("Xiemao\n");
            }
            else
            {
                printf("Fanglaoshi\n");
            }
        }
    }
    return 0;
}

1006 String

一道求最长公共子串的水题。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof(a))
#define FOR(a,b,i) for(i=a;i<=b;++i)
#define For(a,b,i) for(i=a;i<b;++i)
using namespace std;
inline void RD(int &ret)
{
    char c;
    do
    {
        c=getchar();
    }
    while(c<'0'||c>'9');
    ret=c-'0';
    while((c=getchar())>='0'&&c<='9')
    {
        ret=ret*10+(c-'0');
    }
}
inline void OT(int a)
{
    if(a>=10)
    {
        OT(a/10);
    }
    putchar(a%10+'0');
}
char a[1005],b[1005],c[1005];
int dp1[1005][1005],dp2[1005][1005],sum[4005][2],tmp,l1,l2,l3;
void lcs(char *str,int l)//求最长公共子串
{
    int i,j,k;
    FOR(1,l,i)
    {
        if(str[i]==c[1])
        {
            k=1;
            for(j=i;j<=l&&k<=l3;j++)
            {
                if(str[j]==c[k])
                {
                    k++;
                }
            }
            if(k!=l3+1)
            {
                break;
            }
            sum[tmp][0]=i;
            sum[tmp][1]=j-1;
            tmp++;
        }
    }
}
int main()
{
    int t,cas=0,i,j,x,y,ans;
    RD(t);
    while(t--)
    {
        cas++;
        scanf("%s%s%s",a+1,b+1,c+1);
        l1=strlen(a+1);
        l2=strlen(b+1);
        l3=strlen(c+1);
        mem(dp1,0);
        mem(dp2,0);
        FOR(1,l1,i)//dp过程
        {
            FOR(1,l2,j)
            {
                if(a[i]==b[j])
                {
                    dp1[i][j]=dp1[i-1][j-1]+1;
                }
                else
                {
                    dp1[i][j]=max(dp1[i-1][j],dp1[i][j-1]);
                }
            }
        }
        for(i=l1; i>=1; i--)
        {
            for(j=l2; j>=1; j--)
            {
                if(a[i]==b[j])
                {
                    dp2[i][j]=dp2[i+1][j+1]+1;
                }
                else
                {
                    dp2[i][j]=max(dp2[i+1][j],dp2[i][j+1]);
                }
            }
        }
        tmp=0;
        lcs(a,l1);
        x=tmp;
        lcs(b,l2);
        y=tmp-x;
        ans=0;
        For(0,x,i)
        {
            For(0,y,j)
            {
                ans=max(ans,dp1[sum[i][0]-1][sum[j+x][0]-1]+dp2[sum[i][1]+1][sum[j+x][1]+1]);
            }
        }
        printf("Case #%d: %d\n",cas,ans+l3);
    }
    return 0;
}

1004 我们队也做出来了,但我暂时还没有研究,据说是个treeDP,但貌似是枚举树的直径。。不懂啦,等待AC

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值