• 【题解】球迷购票问题-C++


    题目背景
    盛况空前的足球赛即将举行。球赛门票售票处排起了球迷购票长龙。

    按售票处规定,每位购票者限购一张门票,且每张票售价为50元。在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值100元的钱币。假设售票处在开始售票时没有零钱。试问这2N个球迷有多少种排队方式可使售票处不致出现找不出钱的尴尬局面。

    题目描述
    例如当n=2是,用A表示手持50元面值的球迷,用B表示手持100元钱的球迷。则最多可以得到以下两组不同的排队方式,使售票员不至于找不出钱。

    第一种:A A B B

    第二种:A B A B

    [编程任务]

    对于给定的n (0≤n≤20),计算2N个球迷有多少种排队方式,可以使售票处不至于找不出钱。

    输入输出格式
    输入格式:
    一个整数,代表N的值

    输出格式:
    一个整数,表示方案数

    输入输出样例
    输入样例#1:
    2
    输出样例#1:
    2
    说明
    必开QWORD

    测试:N=15

    回溯:1秒(超时)

    模拟栈:大于10分钟

    递归算法:1秒(超时)

    动态规划:0 MS

    组合算法:16 MS

    题意:每个100元来之前必须有一个没走的50元,然后一起原地消失,让人想起了括号匹配
    这道题目给出的方向已经很明确了(说明都给你测试了)
    很显然,可行的操作只有动规和组合算法。
    但是!不信邪的摸鱼酱用没有回溯的DFS跑了一遍感觉还行,20组数组超时了4组(17,18,19,20)
    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,cnt;
    void dfs(int a,int b,int step)
    {
    	if(b<a)return;
    	if(a<0||b<0)return;
    	if(step==2*n)
    	{
    		cnt++;
    		return;
    	}
    	dfs(a-1,b,step+1);
    	if(b>=a)dfs(a,b-1,step+1);
    }
    int main()
    {
    	cin>>n;
    	dfs(n,n,0);
    	cout<<cnt<<endl;
    	return 0;
    }
    

    思路很清晰,来50的或者来100的,不符合情况直接return,代码也很简单。
    但是终究是A不了啊!
    倔强的摸鱼酱依然没有考虑给出的那两种可行方法
    自学了卡特兰数立志用膜法打败膜法
    用到了上面链接那篇博客的公式②,想了解的可以去看一下。
    代码没想到比DFS还要简单...
    DFS 21行,这个只有11行
    极简代码:

    #include<bits/stdc++.h>
    using namespace std;
    long long h[20+2]={1,1},n;
    int main()
    {
    	cin>>n;
    	for(int i=2;i<=n;i++)
    		h[i]=h[i-1]*(4*i-2)/(i+1);
    	cout<<h[n]<<endl;
    	return 0;
    }
    

    ov.

    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    Cookies的实际存储位置
    搭建Git本地服务器
    在Tomcat中部署war
    Server.xml配置解析
    Tomcat配置详解,配置文件server.xml详解
    将centos7打造成桌面系统
    英语词汇大全
    商场/超市常见英语标识
    商务英语词汇大全
    常用繁体字大全
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11234332.html
Copyright © 2020-2023  润新知