从一道题目看蓝桥杯与ACM的区别

我不讨论蓝桥杯的好坏,也不吹捧acm,就从一道题目来看两者的区别。当然我并不是用前者的一道简单题和World final的真题来进行比较,不然就没有意义了,这篇博客的意义就在于前者和后者思考问题思路的不同之处。

废话说完,看题。蓝桥杯某题:一副扑克牌,去掉大小王,剩52张牌,均分给4人,每人13张牌,若不计花色,则这13张牌的可能序列有多少种?-->这原本是一道经典的多重集组合问题,用dp求解(秋叶拓哉--挑战程序竞赛),但还是从头开始看吧。

拿到题目,其一:固定的输入数据,其二:没有指明运行效率。于是诞生了第一种想法,暴力+for循环。

#include <iostream>  
#include <algorithm>  
#include <cstdio>  
#include <cstdlib>  
#include <cmath>  
#include <cstring>  
using namespace std;  
int main()  
{  
    int i,t,ans=0,a[20];  
    for (a[0]=0;a[0]<5;a[0]++)  
    for (a[1]=0;a[1]<5;a[1]++)  
    for (a[2]=0;a[2]<5;a[2]++)  
    for (a[3]=0;a[3]<5;a[3]++)  
    for (a[4]=0;a[4]<5;a[4]++)  
    for (a[5]=0;a[5]<5;a[5]++)  
    for (a[6]=0;a[6]<5;a[6]++)  
    for (a[7]=0;a[7]<5;a[7]++)  
    for (a[8]=0;a[8]<5;a[8]++)  
    for (a[9]=0;a[9]<5;a[9]++)  
    for (a[10]=0;a[10]<5;a[10]++)  
    for (a[11]=0;a[11]<5;a[11]++)  
    for (a[12]=0;a[12]<5;a[12]++)  
    {  
        t=0;  
        for (i=0;i<13;i++) t+=a[i];  
        if (t==13) ans++;  
    }  
    printf("%d",ans);  
    return 0;  
}  
引用了某钊的代码。

的确通俗易懂(QAQ)。

第一是如果是不固定的数据组数呢?for循环就没法解决了,但是谁让题目是死的呢。于是有了第二个思路,暴力+dfs

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int res;
void dfs(int number,int ans)
{
    if(number==14)
        return ;
    if(ans==13)
    {
        res++;
        return;
    }
    for(int i=0;i<=4;i++)
        dfs(number+1,ans+i);
}
int main()
{
    res=0;
    dfs(0,0);
    printf("%d\n",res);
    return 0;
}
然后就是等待数秒后,会出现正确答案,注意,是等待数秒。用dfs的好处是,如果题目改变输入,也可灵活得到答案,其二,不用机械性的敲13个for循环。但是作为一个acmer,应该考虑的不是这些问题,而是如何设计出1s的程序。

于是诞生了DP求解此题:

一共13种牌,dp[i][j]表示在前i种中选取j张的可能情况。

状态转移方程:dp[i][j]=dp[i][j-k]+..d[i][j](k从0到min(j,a[i]))  a[i]表示每种牌的个数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
int dp[100][100];
int w[100];
void solve(int n,int m)
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=n;i++)
        dp[i][0]=1;
    for(int i=0;i<n;i++)
        for(int j=1;j<=m;j++)
    {
        for(int k=0;k<=min(j,w[i]);k++)
            dp[i+1][j]+=dp[i][j-k];
    }
    printf("%d\n",dp[n][m]);
}
//3598180
int main()
{
    int n,m;
    while(~rd2(n,m))
    {
        for(int i=0;i<n;i++)
            rd(w[i]);
        solve(n,m);
    }
    return 0;
}
此时,已经能高效的运行了,这才是真正的程序,当然还有改进之处,原来时间复杂度为O(nm^2),状态转移方程还是可以优化的。

dp[i+1][j]=dp[i+1][j-1]+dp[i][j]-dp[i][j-1-ai]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
const int M=10000007;
int dp[100][100];
int w[100];
void solve(int n,int m)
{
    memset(dp,0,sizeof(dp));
    for(int i=0;i<=n;i++)
        dp[i][0]=1;
    for(int i=0;i<n;i++)
        for(int j=1;j<=m;j++)
    {
        if(j-1-w[i]>=0)
        dp[i+1][j]=(dp[i+1][j-1]+dp[i][j]-dp[i][j-1-w[i]]+M)%M;
        else
        dp[i+1][j]=dp[i+1][j-1]+dp[i][j];
    }
    printf("%d\n",dp[n][m]);
}
//3598180
int main()
{
    int n,m;
    while(~rd2(n,m))
    {
        for(int i=0;i<n;i++)
            rd(w[i]);
        solve(n,m);
    }
    return 0;
}
这样复杂度讲到了O(nm),参考(秋叶拓哉)的多重集组合数章节。

怎么说呢,蓝桥杯也并不是水,考的比较差的我也没这个资格说,但是对于一直在刷acm题的我来说,也让我发现了很多漏洞,好比说,经典的dfs还没有掌握,dp的知识也暂时没有涉及太多,树形dp,状压dp.etc 都还没做。总之我感觉acm更多的是锻炼人的思维,而蓝桥杯则更偏向于对经典算法的涉猎程度,当然我并不是说acm涉猎不广,两者的难度我相信不用我比较也是不言而喻的,那么就借此题给之前自以为是的我画个句号吧。




  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
蓝桥杯国赛是中国最大的计算机竞赛之一,参加者需要在规定的时间内完成一系列的编程题目蓝桥杯国赛的竞争非常激烈,每年都有数以万计的学生报名参赛。 我很荣幸地告诉大家,我在最近一次的蓝桥杯国赛中获得了三等奖。这对我来说是一项非常重要的成就,也是我多年来努力学习计算机科学的回报。 在获得三等奖的过程中,我遇到了很多挑战。首先是题目度,比赛中出现的问题需要有深厚的计算机基础和扎实的编程能力。其次,在限定的时间内完成多个题目也需要灵活的思维和高效的执行能力。此外,比赛还有一定的压力和紧张氛围,需要保持冷静和集中精力。 在准备蓝桥杯国赛之前,我付出了大量的时间和精力。我参加了许多培训班和辅导课程,学习了算法、数据结构和编程技巧。我还刷了很多以往比赛的真题,提高了自己的编程水平。除此之外,我还积极参与学校的ACM俱乐部活动,和其他同学一起切磋学习,相互交流经验。 获得三等奖对我来说是一种认可和鼓励。它让我相信,只要付出努力并持之以恒,就能够获得回报。同时,这也增强了我的自信心,让我更加坚定地向着更高的目标迈进。 对我来说,蓝桥杯国赛不仅是一次比赛,更是一次学习和成长的机会。它推动着我不断提升自己,探索计算机科学的无限可能。我会继续努力学习,为以后的比赛做好准备,争取取得更好的成绩。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值