• 理工 校赛 题


    lzp穿鞋带的理论方法

    发布时间: 2017年12月11日 14:01   最后更新: 2017年12月11日 14:46   时间限制: 1000ms   内存限制: 128M

    对于鞋,lzp有一套奇怪的穿鞋带理论:

    0.鞋带孔之间的鞋带不能是弯的,即鞋带穿过两鞋带孔时必须绷直。

    1.鞋带必须从最前面的一头左端穿入,并从最前面右端穿出,如图所示为一些普qi通pa的穿鞋带方法,○表示鞋带孔,直线表示鞋带。

    c7d12bb4edd31959a7136abbddc237e5.png14ac3b41ef97c2b7419b4626b5ea2d9b.png

    shoe5.png

    2.穿鞋带时,必须左右交替,如上图所示

    3.穿完的鞋带必须存在m个以上的交点,上图左边的共有四个交点,右边的有九个交点。lzp的鞋保证所有交点都只被鞋带经过两次。

    现在,lzp想知道,对于每只纵向排列着n对鞋带孔的鞋,有几种穿鞋带方案符合他的理论(上图中n=5)

    第一行输入组数T(T<=10)
    每组数据输入两个数n(1<=n<=7),m(0<=m<=1000)

    对于每组数据输出一行,符合lzp的理论的穿鞋带方案数

    7
    5 4
    5 9
    3 2
    1 0
    3 6
    7 10
    6 20
    576
    540
    4
    1
    1
    518269
    10221

    题目分析 : 每次只能重一个点穿过,并且左右交替,点数不多 最多只有7个,那不就是暴力吗,想想要怎么暴力,每次可以交替枚举出所有可能的边,枚举出所有可能的边以后,
    在判断当前的这些边总共有多少个交点,怎么判断两个点是不是相交呢,如果给两列点瞬时标上号,那么(a[1]-a[2])*(b[1]-b[2]) < 0,则说明两条线是相交的,自己可以举几个例子验证一下。

    代码示例 :
    const int eps = 1e6+5;
    const double pi = acos(-1.0);
    const int inf = 1<<29;
    #define Max(a,b) a>b?a:b
    #define Min(a,b) a>b?b:a
    #define ll long long
    
    int p2[20];
    int p1[20];
    
    struct node
    {
        int a, b;
    }pre[eps];
    
    int sign = 1;
    int p;
    ll ans = 0;
    int n, m;
    
    
    bool check(){
        int k = 1;
        for(int i = 2; i <= n; i++){
            pre[k].a = i;
            pre[k++].b = p1[i];
        }    
        for(int i = 1; i <= n; i++){
            pre[k].a = p2[i];
            pre[k++].b = i;
        }
        //printf("k = %d
    ", k);
        int cnt = 0;
        for(int i = 1; i < k; i++){
            for(int j = i+1; j < k; j++){
                if ((pre[i].a - pre[j].a)*(pre[i].b - pre[j].b) < 0){
                    cnt++;
                }
            }
        }
        if (cnt >= m) return true;
        else return false;
    }
    
    void find(int x){
        for(int i = 2; i <= n; i++){
            //if (x == 1) printf("** %d 
    ", sign);
            if (sign && !p2[i]) {
                p2[i] = x;
                sign = 0;
                find(i);
                p2[i] = 0;
                sign = 1;
                
            }
            else if (!sign && !p1[i]){
                p1[i] = x;
                sign = 1;
                p = i;
                find(i);
                p1[i] = 0;
                sign = 0;
            }   
        }
        int t = 0;
        for(int i = 2; i <= n; i++){
            if (p2[i]) t++;
        }
        if (sign && t == n-1) {
            sign = 0;
            p2[1] = p;
            
            if (check()) ans++;
            p2[1] = 0; 
        }
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int t;
        
        
        cin >> t;
        while(t--){
            scanf("%d%d", &n, &m); 
            
            memset(p2, 0, sizeof(p2));
            memset(p1, 0, sizeof(p1));
            ans = 0, sign = 1;
            find(1); 
            printf("%lld
    ", ans);
            
        }
    
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    js 用延时函数来实现像鼠标移入qq头像然后会出现新的模块
    css显示出三角形
    js实现简单的滑动门和tab选项卡
    js的捕捉事件,冒泡事件
    js时间冒泡,阻止事件冒泡
    js鼠标,键盘,坐标轴事件
    js实现自动登陆的按钮
    javascript各种兼容性问题,不断更新
    [LeetCode OJ] Single Number之一 ——Given an array of integers, every element appears twice except for one. Find that single one.
    [LeetCode OJ] Candy
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/8029118.html
Copyright © 2020-2023  润新知