130829组队赛-Regionals 2012, Asia - Jakarta

4 篇文章 0 订阅
2 篇文章 0 订阅

A.Grandpa's Walk

简单的搜索题,此题的题意是将nXm的图中所有能降序走通的道路求出来。就是一个dfs深搜,没有难度。

写得很简单,没有考虑太多。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#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 1000000007
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 dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int n,m,sum,c[51][51];
void dfs(int x,int y)
{
    int i,j,k,g=0;
    For(0,4,k)
    {
        i=x+dx[k];
        j=y+dy[k];
        if(c[i][j]<c[x][y]&&(i>=0&&j>=0&&i<n&&j<m))//深搜
        {
            dfs(i,j);
            g=1;
        }
    }
    if(g==0)
    {
        sum++;
    }
}
int main()
{
    int i,j,k,t,cas=0,a,b,f;
    RD(t);
    while(t--)
    {
        cas++;
        RD(n);
        RD(m);
        For(0,n,i)
        {
            For(0,m,j)
            {
                RD(c[i][j]);
            }
        }
        sum=0;
        For(0,n,i)
        {
            For(0,m,j)
            {
                f=0;
                For(0,4,k)
                {
                    a=i+dx[k];
                    b=j+dy[k];
                    if(c[a][b]>c[i][j]&&(a>=0&&b>=0&&a<n&&b<m))//判断此点能否作为起点
                    {
                        f=1;
                    }
                }
                if(f==0)
                {
                    dfs(i,j);
                }
            }
        }
        printf("Case #%d: %d\n",cas,sum);
    }
    return 0;
}

B.Let's Go Green

咋一眼看上去像是一道图论题,但我图论很水,就再想了一下,发现这是一个比较巧妙的想法题。我们可以将这个图看成一条主干路,边上有一些小的岔路分支,我们首先将所有点周围的连接路径上的BY都加上,并记录它周围BY最多的一条路径。接下去就是计算了,我们首先把所有的分支和端点上路径的BY数都加上,我们可以这样想:所有的支路的BY最后都是要加到主干路上的,有一个分叉就得加上该条的BY数。接下去再分析结点,对于一个BY最多一条路径比剩余BY数还多的结点,我们需要加上最多BY比剩余部分多的内部分,然后再分析一个BY最多一条路径比剩余BY数还少的结点,只要判断是奇数就加上1,不是就不加。可以这样理解(偶数的此种结点其周围BY会自动形成两边相等的情形,所以不需要加,而奇数的该结点两端无法平衡,必然相差1,所以需要加1),最后得到答案后需要除以2,因为这是一个两端相等的和。

说得不太清楚,表达能力有限请原谅~

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#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 1000000007
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');
}
struct xl
{
    int x[100001],y[100001];
}p;
int main()
{
    int t,n,a,b,c,i,z,s,cas=0;
    RD(t);
    while(t--)
    {
        cas++;
        RD(n);
        mem(p.x,0);
        mem(p.y,0);
        z=0;
        for(i=0;i<n-1;++i)
        {
            RD(a);
            RD(b);
            RD(c);
            p.x[a]+=c;
            p.x[b]+=c;
            p.y[a]=max(p.y[a],c);
            p.y[b]=max(p.y[b],c);
        }
        s=0;
        for(i=1;i<=n;++i)
        {
            if(2*p.y[i]>p.x[i])
            {
               s+=(2*p.y[i]-p.x[i]);
            }
            else if(p.x[i]%2==1)
            {
                s+=1;
            }
        }
        printf("Case #%d: %d\n",cas,s/2);
    }
    return 0;
}

C.Stop Growing!

水题不多说,自己看。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#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 1000000007
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 main()
{
    int t,a,b,c,d,e,sum,ans,m,j,cas=0;
    RD(t);
    while(t--)
    {
        cas++;
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&m);
        sum=a+b+c+d+e;
        if(sum<=0&&sum<m)
        {
            printf("Case #%d: -1\n",cas);
        }
        else
        {
            j=0;
            while(sum<m)
            {
                sum*=2;
                j++;
            }
            printf("Case #%d: %d\n",cas,j);
        }
    }
    return 0;
}

G题是个双连通分量,图论渣不会。。。就不写了


I.Tiling

题意,给你六个系数,让你分别求出xi,yi,求这些点中能覆盖的最小面积模块

图给你示意图太误导人了,我们可以直接考虑同一行的x之间的距离就行了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#include <queue>
#include<map>
#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');
}
int gcd(int a,int b)
{
    if(b==0)
    {
        return a;
    }
    return gcd(b,a%b);
}
int det(int a,int b,int x,int y)
{
    return abs(a*y-b*x);
}
int main()
{
    int t,cas=0,i,x1,x2,x3,y1,y2,y3,a,b,c;
    RD(t);
    while(t--)
    {
        cas++;
        scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3);
        a=det(x1,y1,x2,y2);
        b=det(x1,y1,x3,y3);
        c=det(x2,y2,x3,y3);
        printf("Case #%d: %d\n",cas,gcd(a,gcd(b,c)));
    }
    return 0;
}



J.Perfect Matching

简单题,但是容易卡时间,题意就是给你n个字符串,让你两两搭配,看是否为回文字符串。思路一样,有些能AC,有些TLE,这就要看你写得优不优美了~

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<vector>
#include<stack>
#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 1000000007
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[1001][501];
string str;
int main()
{
    int t,n,i,j,cas=0,l,f,sum,k;
    RD(t);
    while(t--)
    {
        cas++;
        RD(n);
        sum=0;
        for(i=0; i<n; ++i)
        {
            scanf("%s",a[i]);
        }
        for(i=0; i<n; ++i)
        {
            for(j=0; j<n; ++j)
            {
                if(i!=j)
                {
                    str=a[i];
                    str+=a[j];
                    l=str.length();
                    f=0;
                    for(k=0; k+k<l; ++k)
                    {
                        if(str[k]!=str[l-k-1])
                        {
                            f=1;
                            break;
                        }
                    }
                    if(f==0)
                    {
                        sum++;
                    }
                }
            }
        }
        printf("Case #%d: %d\n",cas,sum);
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值