2017gdut校赛决赛题解

题目链接:http://www.gdutcode.sinaapp.com/contest.php?cid=1057

Problem A: 两只老虎

解析:列个方程直接可以解出答案,ans = a/2-c/4+b

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        int t1 = c/4-b;
        int ans = a/2-t1;
        printf("%d\n",ans);

    }
    return 0;
}

Problem D: 只有通过毁灭才能揭示真理

解析:直接算就好了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b,c;
        scanf("%d %d %d",&a,&b,&c);
        int ans = a*b+a/30*c;
        printf("%d\n",ans);
    }
    return 0;
}

Problem C: 爬楼梯

解析:数多几个,发现是类斐波那契数列的东西,先把每层的方法数处理好,然后直接相乘即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int dp[25];
int main()
{
    dp[1] = 1;
    dp[2] = 2;
    dp[3] = 4;
    for(int i=4;i<=20;i++)
        dp[i] = dp[i-1]+dp[i-2]+dp[i-3];
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        int ans = 1;
        for(int i=0;i<n-1;i++)
        {
            int x;
            scanf("%d",&x);
            ans = (ans*dp[x])%mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}

Problem E: 倒水(Water)

解析:比赛的时候没想那么多,直接dfs爆搜了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int inf = 0x7fffffff;
int a[maxn];
int n,k;
int ans = inf;
void dfs(int t1,int t2,int t3,int step)
{
    if(step>ans)
        return ;
    if(t1+t2<=k)
        ans = min(ans,step);
    if(t1==1)
        return ;
    if(t1%2)
    {
        dfs(t1/2,t2+1,t3*2,step);
        dfs((t1+1)/2,t2,t3*2,step+t3);
    }
    else
        dfs(t1/2,t2,t3*2,step);
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        scanf("%d %d",&n,&k);
        int tt = n;
        ans = 1;
        while(n!=1)
        {
            if(n%2)
                ans++;
            n/=2;
        }
        if(ans<=k)
            puts("0");
        else
        {
            ans = inf;
            dfs(tt,0,1,0);
            printf("%d\n",ans);
        }
    }
    return 0;
}

Problem H: tmk买礼物

解析:排个序,然后那个ans记录当前可以达到最大的x,然后没加一个a[i],判断他是否满足a[i]<=ans+1,不然的话会出现断层

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int a[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        long long ans = 0;
        sort(a,a+n);
        for(int i=0;i<n;i++)
        {
            if(a[i]<=ans+1)
                ans += a[i];
            else
                break;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Problem B: 占点游戏

解析:首先算出两点之间的曼哈顿距离step,接着判断先手在n轮里面是否能到达对面的出发点((n+1)/2>step?),如果不能到达,n为奇数时,先手比后手多一个,n为偶数就是平手了,如果能够到达,如果曼哈顿距离为奇数时,如果n为偶数的话,先手到达时,后手可以多走一步,故为平手,若n为奇数的话,先手可以比后手多走一步,故领先两点

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int inf = 0x7fffffff;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        int x1,y1,x2,y2;
        scanf("%d %d %d %d %d",&n,&x1,&y1,&x2,&y2);
        int step = abs(x1-x2)+abs(y1-y2);
        int ans;
        if(n%2)
        {
            n/=2+1;
            if(step>n)
                ans = 1;
            else if(step%2)
                ans = 2;
            else
                ans = 1;
        }
        else
        {
            n/=2;
            if(step>n)
                ans = -1;
            else if(step%2)
                ans = -1;
            else
                ans = 1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

Problem F: tmk找三角

解析:由于这个图是一棵树,所以处理最短路的时候直接dfs即可,剩下的是判断是否存在三角形,通常判断是否存在三角形的方法是,把所有边都排个序,判断a[i]是否小于a[i-1]+a[i-2],那么这样肯定是超时的,如果换种思路来考虑的话,如果无法构成三角形,则对于所有的边都有a[i]>=a[i-2]+a[i-1],加上a[i]尽量取得小的话,那就是a[i] = a[i-2]+a[i-1],且a[i-2] = a[i-1] = 1,那这就是一个斐波那契数列了,于是如果不存在三条边能够成三角形的话,那么最长的边至少为f[n],表示斐波那契第n项,而题目边最大为1e9,也就是如果n>50的话,一定是yes,如果n<=50的话,那就按常规的判断即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
const int inf = 0x7fffffff;
struct node
{
    int v;
    int w;
    node() {}
    node(int _v,int _w)
    {
        v = _v;
        w = _w;
    }
};
vector<node>G[maxn];
int du[maxn];
int dis[maxn];
int fa[maxn];
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        G[i].clear();
        fa[i] = i;
    }
    memset(du,0,sizeof(du));

}
void dfs(int u,int d)
{
    du[u] = d;
    for(int i=0;i<G[u].size();i++)
    {
        node now = G[u][i];
        if(now.v == fa[u])
            continue;
        dis[now.v] = now.w;
        fa[now.v] = u;
        dfs(now.v,d+1);
    }
}
int slove(int x,int y)
{
    vector<int>ans;
    while(ans.size()<50 && x!=y)
    {
        if(du[x]<du[y])
        {
            ans.push_back(dis[y]);
            y = fa[y];
        }
        else
        {
            ans.push_back(dis[x]);
            x = fa[x];
        }
    }
    if(ans.size()>=50)
        return 1;
    sort(ans.begin(),ans.end());
    for(int i=2;i<ans.size();i++)
    {
        if(ans[i]<ans[i-1]+ans[i-2])
            return 1;
    }
    return 0;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        init(n);
        for(int i=0;i<n-1;i++)
        {
            int a,b,len;
            scanf("%d %d %d",&a,&b,&len);
            G[a].push_back(node(b,len));
            G[b].push_back(node(a,len));
        }
        dfs(1,0);
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int x,y;
            scanf("%d %d",&x,&y);
            if(slove(x,y))
                puts("Yes");
            else
                puts("No");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值