zoukankan      html  css  js  c++  java
  • 记一道“芯片升级消耗”数学题

            

    要求

    • 现有一堆特殊芯片和普通芯片,芯片等级分为0-6级,芯片都可以合成升级,普通芯片和特殊芯片升级都消耗一定钱数和同等级普通芯片数。配置表如上,比如:升级一个0级特殊芯片到1级,需要消耗自身和2个0级普通芯片共3个芯片,花费为1;升级一个1级普通芯片到2级,需要消耗自身和2个1级普通芯片共3个芯片,花费为2。这里只讨论升级特殊芯片。要求实现设计图所示所有功能。

    实现思路

    • 首先把特殊芯片和普通芯片分类,因为6级已是满级无法再升级,所以特殊芯片中再去除6级芯片,剩下的特殊芯片都是有可能升级的芯片。
    • “合成等级”默认比芯片自身高一级,最低比芯片自身高一级,最高为6级。
    • “合成数量” 默认为1,实际数量多少后面程序会修正。
    • 根据前面的“合成等级”和“合成数量”,再计算出“花费”具体数。
    • 界面初始化时,程序会计算所有特殊芯片的“合成等级”和“合成数量”,如果某芯片无法升级,会修正该芯片“合成数量”为0,“花费”为0。
    • 点击某芯片“合成等级”或“合成数量”加减按钮,该芯片前的所有芯片“合成等级”、“合成数量”数不变,而它后面所有芯片的“合成等级”不变,“合成数量”数需要程序修正,如果仍可升级则不变,否则数量减1尝试升级,如果仍不能升级则继续减1尝试,直至数量为0。例如,可升级特殊芯片依次为A、B、C、D,将B的“合成数量”加1,A的“合成等级”、“合成数量”数不动,C、D的“合成等级”不动、“合成数量”程序修正。

    讨论重点

    • 这里主要讨论:在普通芯片数量有限的前提下,特殊芯片的升级消耗普通芯片数量算法和花费算法。
    • 测试用例:普通芯片消耗库有100个0级普通芯片,1个1级普通芯片,1个2级普通芯片。现有1个0级特殊芯片,尝试合成等级为3级,合成数量为1。
    • 首先,初始化配置表和普通芯片消耗库,这里用Dictionary<int, int>简单实现。cfg_num的key为等级,value为消耗芯片数;cfg_cost的key为等级,value为花费。
    Dictionary<int, int> cfg_num = new Dictionary<int, int>();
    Dictionary<int, int> cfg_cost = new Dictionary<int, int>();
    Dictionary<int, int> expDic = new Dictionary<int, int>();
    
    public void InitCfg()
    {
        // 所需消耗数量配置
        cfg_num = new Dictionary<int, int>();
        cfg_num[0] = 3;
        cfg_num[1] = 3;
        cfg_num[2] = 3;
        cfg_num[3] = 3;
        cfg_num[4] = 3;
        cfg_num[5] = 3;
        cfg_num[6] = 0;
    
        // 花费配置
        cfg_cost = new Dictionary<int, int>();
        cfg_cost[0] = 1;
        cfg_cost[1] = 2;
        cfg_cost[2] = 3;
        cfg_cost[3] = 4;
        cfg_cost[4] = 5;
        cfg_cost[5] = 6;
        cfg_cost[6] = 0;
    
    }
    
    // 初始化普通芯片消耗库
    public void InitExpDic()
    {
        expDic[0] = 100;
        expDic[1] = 1;
        expDic[2] = 1;
        expDic[3] = 0;
        expDic[4] = 0;
        expDic[5] = 0;
        expDic[6] = 0; // 6级普通芯片数目肯定是0
    
    }
    • 将要求合成等级的特殊芯片全部转化为0级芯片,得到所要消耗0级芯片总数即“总消耗”。将初始特殊芯片自身全部转化为0级芯片,普通芯片消耗库符合部分也全部转化为0级芯片,两者相加得到“总拥有”。当总拥有 >= 总消耗,即可升级。
    public bool CanUp(int needLv, int needNum, int itsLv)
    {
        if (needLv == 0 || needNum == 0)
        {
            return true;
        }
        // 总消耗
        Dictionary<int, int> costDic = new Dictionary<int, int>();
        for (int i = 0; i <= 6; i++)
        {
            costDic[i] = 0;
        }
        costDic[needLv] = needNum;
        // 总拥有 = 普通芯片消耗库符合部分 + 自身
        Dictionary<int, int> gotDic = new Dictionary<int, int>();
        for (int i = 0; i <= 6; i++)
        {
            gotDic[i] = expDic[i];
        }
        gotDic[itsLv] += 1;
        int costZeroNum = GetZeroNum(costDic, needLv, 0);
        int gotZeroNum = GetZeroNum(gotDic, needLv - 1, 0);
        return gotZeroNum >= costZeroNum;
        
    }
    
    public int GetExpDicZeroSum()
    {
        return GetZeroNum(expDic, 6, 0);
    }
    
    // 从level开始往前,所有芯片都转换成0级普通芯片
    public int GetZeroNum(Dictionary<int, int> dic, int level, int extraNum)
    {
        if (level == 0)
        {
            return dic[0] + extraNum;
        }
        int num = (dic[level] + extraNum) * cfg_num[level - 1];
        return GetZeroNum(dic, level - 1, num);
    
    }
    • 花费算法如下,因为该算法会真正扣去普通芯片库的相关数量,所以需要确定特殊芯片能升级再使用。
    // 能升级再算花费
    public int ApplyCost(Dictionary<int, int> expDic, int needLv, int needNum, int itsLv)
    {
        if (needNum <= 0 || needLv == 0)
        {
            return 0;
        }
        int cost = needNum * cfg_cost[needLv - 1];
        int num = cfg_num[needLv - 1];
        if (itsLv == needLv - 1)
        {
            num -= 1;
        }
        int leftNum = needNum * cfg_num[needLv - 1] - expDic[needLv - 1];
        if (itsLv == needLv - 1)
        {
            leftNum -= 1;
        }
        if (leftNum > 0)
        {
            expDic[needLv - 1] = 0;
        }
        else
        {
            expDic[needLv - 1] = Math.Abs(leftNum);
        }
        cost += ApplyCost(expDic, needLv - 1, leftNum, itsLv);
        return cost;
        
    }
    • 测试用例如下
    public void Test()
    {
        InitCfg();
        InitExpDic();
        PrintExpDic();
        Console.WriteLine();
        int itsLv = 0;
        int needLv = 3;
        int needNum = 1;
        Console.WriteLine("{0}级特殊芯片,合成等级:{1}级,合成数量:{2}个", itsLv, needLv, needNum);
        if (CanUp(needLv, needNum, itsLv))
        {
            Console.WriteLine("合成成功");
            int cost = ApplyCost(expDic, needLv, needNum, itsLv);
            Console.WriteLine("共花费: {0}", cost);
            PrintExpDic();
        }
        else
        {
            Console.WriteLine("合成失败");
        }
    }
    • 得到打印如下,“1个0级特殊芯片,尝试合成等级为3级,合成数量为1”,需要14个0级普通芯片,1个1级芯片,1个2级普通芯片。

    • 全部代码如下
    using System;
    using System.Collections.Generic;
    
    namespace CanDDel
    {
        public class Solution
        {
            Dictionary<int, int> cfg_num = new Dictionary<int, int>();
            Dictionary<int, int> cfg_cost = new Dictionary<int, int>();
            Dictionary<int, int> expDic = new Dictionary<int, int>();
    
            public void Test()
            {
                InitCfg();
                InitExpDic();
                PrintExpDic();
                Console.WriteLine();
                int itsLv = 0;
                int needLv = 3;
                int needNum = 1;
                Console.WriteLine("{0}级特殊芯片,合成等级:{1}级,合成数量:{2}个", itsLv, needLv, needNum);
                if (CanUp(needLv, needNum, itsLv))
                {
                    Console.WriteLine("合成成功");
                    int cost = ApplyCost(expDic, needLv, needNum, itsLv);
                    Console.WriteLine("共花费: {0}", cost);
                    Console.WriteLine();
                    PrintExpDic();
                }
                else
                {
                    Console.WriteLine("合成失败");
                }
            }
    
            public void InitCfg()
            {
                // 所需消耗数量配置
                cfg_num = new Dictionary<int, int>();
                cfg_num[0] = 3;
                cfg_num[1] = 3;
                cfg_num[2] = 3;
                cfg_num[3] = 3;
                cfg_num[4] = 3;
                cfg_num[5] = 3;
                cfg_num[6] = 0;
    
                // 花费配置
                cfg_cost = new Dictionary<int, int>();
                cfg_cost[0] = 1;
                cfg_cost[1] = 2;
                cfg_cost[2] = 3;
                cfg_cost[3] = 4;
                cfg_cost[4] = 5;
                cfg_cost[5] = 6;
                cfg_cost[6] = 0;
    
            }
    
            // 初始化普通芯片消耗库
            public void InitExpDic()
            {
                expDic[0] = 100;
                expDic[1] = 1;
                expDic[2] = 1;
                expDic[3] = 0;
                expDic[4] = 0;
                expDic[5] = 0;
                expDic[6] = 0; // 6级普通芯片数目肯定是0
    
            }
    
            public bool CanUp(int needLv, int needNum, int itsLv)
            {
                if (needLv == 0 || needNum == 0)
                {
                    return true;
                }
                // 总消耗
                Dictionary<int, int> costDic = new Dictionary<int, int>();
                for (int i = 0; i <= 6; i++)
                {
                    costDic[i] = 0;
                }
                costDic[needLv] = needNum;
                // 总拥有 = 普通芯片消耗库 + 自身
                Dictionary<int, int> gotDic = new Dictionary<int, int>();
                for (int i = 0; i <= 6; i++)
                {
                    gotDic[i] = expDic[i];
                }
                gotDic[itsLv] += 1;
                int costZeroNum = GetZeroNum(costDic, needLv, 0);
                int gotZeroNum = GetZeroNum(gotDic, needLv, 0);
                return gotZeroNum >= costZeroNum;
    
            }
    
            public int GetExpDicZeroSum()
            {
                return GetZeroNum(expDic, 6, 0);
    
            }
    
            // 从level开始往前,所有芯片都转换成0级普通芯片
            public int GetZeroNum(Dictionary<int, int> dic, int level, int extraNum)
            {
                if (level == 0)
                {
                    return dic[0] + extraNum;
                }
                int num = (dic[level] + extraNum) * cfg_num[level - 1];
                return GetZeroNum(dic, level - 1, num);
    
            }
    
            // 能升级再算花费
            public int ApplyCost(Dictionary<int, int> expDic, int needLv, int needNum, int itsLv)
            {
                if (needNum <= 0 || needLv == 0)
                {
                    return 0;
                }
                int cost = needNum * cfg_cost[needLv - 1];
                int num = cfg_num[needLv - 1];
                if (itsLv == needLv - 1)
                {
                    num -= 1;
                }
                int leftNum = needNum * cfg_num[needLv - 1] - expDic[needLv - 1];
                if (itsLv == needLv - 1)
                {
                    leftNum -= 1;
                }
                if (leftNum > 0)
                {
                    expDic[needLv - 1] = 0;
                }
                else
                {
                    expDic[needLv - 1] = Math.Abs(leftNum);
                }
                cost += ApplyCost(expDic, needLv - 1, leftNum, itsLv);
                return cost;
    
            }
    
            public void PrintExpDic()
            {
                Console.WriteLine("普通芯片库当前数量:");
                foreach (KeyValuePair<int, int> item in expDic)
                {
                    Console.WriteLine("等级:{0}, 数量:{1}", item.Key, item.Value);
                }
    
            }
    
        }
        
    }
  • 相关阅读:
    获取汉字信息(结合正则就可以得到想要的详细啦)
    压缩图片(递归结合pillow)通过改变图片尺寸实现;tinify 需要付费
    实现两个视频同时播放,利用到opencv模块 (线程进程开启)
    切换pip下载源头
    516. 最长回文子序列
    87.扰乱字符串
    Maximum Likelihood ML
    数组右边第一个比当前元素大的数
    4. 寻找两个正序数组的中位数
    min-hash
  • 原文地址:https://www.cnblogs.com/caiger-blog/p/12993889.html
Copyright © 2011-2022 走看看