zoukankan      html  css  js  c++  java
  • 小学奥数之称球问题

    题目描述

    给定 (n) 个无标号的球,(n-1) 个的重量相同,剩下 (1) 个球的重量比这 (n-1) 个球略重

    给定一个天平,每次可以用天平称量,天平的一边最多放 (m) 个球,求最劣情况下找出略重那个球的最小步数

    题解

    如果天平放的球的个数没有限制

    最优决策是将球分成三堆

    • (3n),直接分成 (n, n, n) 就行了

    • (3n + 1),分成 (n, n, n+1),用天平称 (n,n) 这两堆,最劣的情况是那个特殊球在 (n+1)

    • (3n + 2),分成 (n, n+1, n+1),用天平称 (n+1,n+1) 这两堆,最劣的情况就是那个特殊球在这两个 (n+1)


    如果天平有限制

    最先会限制到上面的第三种情况,即 (n+1>m),总球数 (3n+2>3m-1),显然这时只能拿出两个 (m) 去称,最劣的情况是剩下没称的那一堆,即转移到 (f(n-2m)),这个显然可以 (Theta(1)) 转移

    代码
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define ll long long
    #define rint register int 
    #define rll register long long
    
    using namespace std;
    
    const int maxn = 1e5 + 50, INF = 0x3f3f3f3f;
    
    inline ll read () {
    	rll x = 0, w = 1;
    	char ch = getchar ();
    	for (; ch < '0' || ch > '9'; ch = getchar ()) if (ch == '-') w = -1;
    	for (; ch >= '0' && ch <= '9'; ch = getchar ()) x = x * 10 + ch - '0';
    	return x * w;
    }
    
    ll n, m;
    
    inline ll DFS (ll n) {
    	if (n == 1 || n == 0) return 0;
    	if (n >= 3 * m + 2) {
    		rll res = (n - m - 2) / (2 * m);
    		return DFS (n - 2 * res * m) + res;
    	} else {
    		if (n % 3 == 0) return DFS (n / 3) + 1;
    		else if (n % 3 == 1) return DFS (n / 3 + 1) + 1;
    		else return DFS (n / 3 + 1) + 1;
    	}
    }
    
    int main () {
    	n = read(), m = read();
    	printf ("%lld
    ", DFS (n));
    	return 0;
    }
    
  • 相关阅读:
    [SCOI2009] Windy数
    [P1361] 小M的作物
    Wannafly Camp 2020 Day 2E 阔力梯的树
    2017百越杯反序列化writeup
    大美西安writeup
    Thinkphp的SQL查询方式
    Thinkphp的CURD
    记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)
    ThinkPHP的输出和模型使用
    ThinkPHP的运行流程-2
  • 原文地址:https://www.cnblogs.com/Rubyonly233/p/14617740.html
Copyright © 2011-2022 走看看