头像

GRID




离线:9小时前


最近来访(726)
用户头像
LKW121
用户头像
逺い
用户头像
kyohyper
用户头像
LonelyLove
用户头像
sszj
用户头像
Kabalt
用户头像
一半醒
用户头像
宇宙有边
用户头像
WangJY
用户头像
蓬蒿人
用户头像
崔巉
用户头像
陆修远
用户头像
werasdxcv345
用户头像
acwing_86787
用户头像
acwing_29526
用户头像
ㅤㅤㅤㅤㅤㅤㅤㅤ
用户头像
玖蕴潜辉
用户头像
算法小白
用户头像
qujunyi
用户头像
Boom_1


GRID
9天前

Minecraft 1.16.5模组开发3D盔甲

Minecraft 1.12.2模组开发3D盔甲

我们本次在1.18.2的版本中实现具有动画效果的3D盔甲

1.首先,为了实现这些效果,我们需要首先使用到一个模组:geckolib(下载地址)

找到项目的build.gradle文件,在repositoriesdependencies中添加依赖。

repositories {

    //添加这个
    maven { url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' }

}
dependencies {
    minecraft 'net.minecraftforge:forge:1.18.2-40.1.0'

    //添加这个
    implementation fg.deobf('software.bernie.geckolib:geckolib-1.18-forge:3.0.18')

}

cr4.png

之后我们重新构建gradle项目

cr5.png

构建好了项目后在项目的Main类中添加一句geckolib的初始化语句:

Main.java

    public Main() {
        IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();

        ItemInit.ITEMS.register(bus);


        //添加GeckoLib初始化函数
        GeckoLib.initialize();


        MinecraftForge.EVENT_BUS.register(this);
    }

2.之后,与之前的教程一样,我们需要在blockbench中制作一个模组中的3D盔甲:

进入软件后我们要找到一个插件按钮,然后再搜索栏中输入GeckoLib Animation Utils,并下载这个插件

cr6.png

将我们制作好的生物实体进行模型转换工作,找到Convert Project,之后选择Geckolib Animated Model

cr7.png

在这之后,你会发现你的生物实体栏多了一个Animate栏,点击进去:

crr.jpg

具体动作制作的视频:Blockbench动画制作

注:我们的盔甲的要完全按照这种进行制作:

crr1.jpg

在制作好所有的动画后我们导出模型和动画json文件。

cc.png

3.模型制作完成,接下来需要制作我们的盔甲类

在items包中新建armor包 -> armor包中新建我们的套装类HeisensuitArmorItem

HeisensuitArmorItem.java

package com.joy187.re8joymod.items.armor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ImmutableMap;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.init.EffectInit;
import com.joy187.re8joymod.init.ItemInit;
import com.joy187.re8joymod.util.CustomArmorMaterial;

import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ArmorItem;
import net.minecraft.world.item.ArmorMaterial;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import software.bernie.geckolib3.core.IAnimatable;
import software.bernie.geckolib3.core.PlayState;
import software.bernie.geckolib3.core.builder.AnimationBuilder;
import software.bernie.geckolib3.core.controller.AnimationController;
import software.bernie.geckolib3.core.event.predicate.AnimationEvent;
import software.bernie.geckolib3.core.manager.AnimationData;
import software.bernie.geckolib3.core.manager.AnimationFactory;
import software.bernie.geckolib3.item.GeoArmorItem;


public class HeisensuitArmorItem extends GeoArmorItem implements IAnimatable{
    private AnimationFactory factory = new AnimationFactory(this);

    public HeisensuitArmorItem(ArmorMaterial materialIn, EquipmentSlot slot, Properties builder) {
        super(materialIn, slot, builder.tab(Main.TUTORIAL_TAB));
    }

    //动画状态机,判断每个时刻我们的盔甲的动画状态
    @SuppressWarnings("unused")
    private <P extends IAnimatable> PlayState predicate(AnimationEvent<P> event) {
        // This is all the extradata this event carries. The livingentity is the entity
        // that's wearing the armor. The itemstack and equipmentslottype are self
        // explanatory.
        List<EquipmentSlot> slotData = event.getExtraDataOfType(EquipmentSlot.class);
        List<ItemStack> stackData = event.getExtraDataOfType(ItemStack.class);
        LivingEntity livingEntity = event.getExtraDataOfType(LivingEntity.class).get(0);

        // Always loop the animation but later on in this method we'll decide whether or
        // not to actually play it
        event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.heisensuit.idle", true));

        // If the living entity is an armorstand just play the animation nonstop
        if (livingEntity instanceof ArmorStand) {
            return PlayState.CONTINUE;
        }

        // The entity is a player, so we want to only play if the player is wearing the
        // full set of armor
        else if (livingEntity instanceof Player) {
            Player player = (Player) livingEntity;

            // Get all the equipment, aka the armor, currently held item, and offhand item
            List<Item> equipmentList = new ArrayList<>();
            player.getAllSlots().forEach((x) -> equipmentList.add(x.getItem()));

            // 包含四个盔甲位置
            List<Item> armorList = equipmentList.subList(2, 6);

            //如果玩家穿上了所有的套装就会播放相应的动画
            // Make sure the player is wearing all the armor. If they are, continue playing
            // the animation, otherwise stop
            //ItemInit.HEISEN_BOOTS.get(), ItemInit.HEISEN_LEGGINGS.get(),ItemInit.HEISEN_CHEST.get(), ItemInit.HEISEN_HEAD.get()
            boolean isWearingAll = armorList
                    .containsAll(Arrays.asList(ItemInit.HEISEN_BOOTS.get(), ItemInit.HEISEN_LEGG.get()
                            ,ItemInit.HEISEN_SUIT.get(), ItemInit.HEISEN_HEAD.get()));
            return isWearingAll ? PlayState.CONTINUE : PlayState.STOP;
        }
        return PlayState.STOP;
    }

    //将我们的待机动画进行注册
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void registerControllers(AnimationData data) {
        data.addAnimationController(new AnimationController(this, "controller", 20, this::predicate));
    }

    @Override
    public AnimationFactory getFactory() {
        return this.factory;
    }

    private static final Map<ArmorMaterial, MobEffectInstance> MATERIAL_TO_EFFECT_MAP =
            (new ImmutableMap.Builder<ArmorMaterial, MobEffectInstance>())
                    .put(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT,
                            new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 100, 1)).build();

    //穿上后给予效果
    @Override
    public void onArmorTick(ItemStack stack, Level world, Player player) {
        if(!world.isClientSide()) {
            //穿上头盔就给予一个药水效果
            if(!player.getInventory().getArmor(3).isEmpty()) {
                MobEffectInstance mapStatusEffect1 = new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 100, 2);
                ArmorItem helmet = ((ArmorItem)player.getInventory().getArmor(3).getItem());
                if(helmet.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
                    boolean hasPlayerEffect = player.hasEffect(mapStatusEffect1.getEffect());
                    if(!hasPlayerEffect) {
                        player.addEffect(new MobEffectInstance(mapStatusEffect1.getEffect(),mapStatusEffect1.getDuration(), mapStatusEffect1.getAmplifier()));
                    }
                }
            }
            //穿上胸甲就给予一个药水效果
            if(!player.getInventory().getArmor(2).isEmpty()) {
                MobEffectInstance mapStatusEffect2 = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 100, 1);

                ArmorItem breastplate = ((ArmorItem)player.getInventory().getArmor(2).getItem());
                if(breastplate.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
                    boolean hasPlayerEffect = player.hasEffect(mapStatusEffect2.getEffect());
                    if(!hasPlayerEffect) {
                        player.addEffect(new MobEffectInstance(mapStatusEffect2.getEffect(),mapStatusEffect2.getDuration(), mapStatusEffect2.getAmplifier()));
                    }
                }
            }   
            //穿上护腿就给予一个药水效果
            if(!player.getInventory().getArmor(1).isEmpty()) {
                MobEffectInstance mapStatusEffect3 = new MobEffectInstance(MobEffects.SLOW_FALLING, 100, 1);

                ArmorItem leggings = ((ArmorItem)player.getInventory().getArmor(1).getItem());
                if(leggings.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
                    boolean hasPlayerEffect = player.hasEffect(mapStatusEffect3.getEffect());
                    if(!hasPlayerEffect) {
                        player.addEffect(new MobEffectInstance(mapStatusEffect3.getEffect(),mapStatusEffect3.getDuration(), mapStatusEffect3.getAmplifier()));
                    }
                }
            }
            //穿上靴子就给予一个药水效果
            if(!player.getInventory().getArmor(0).isEmpty()) {
                MobEffectInstance mapStatusEffect4 = new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 100, 0);
                ArmorItem boots = ((ArmorItem)player.getInventory().getArmor(0).getItem());
                if(boots.getMaterial() == CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT) {
                    boolean hasPlayerEffect = player.hasEffect(mapStatusEffect4.getEffect());
                    if(!hasPlayerEffect) {
                        player.addEffect(new MobEffectInstance(mapStatusEffect4.getEffect(),mapStatusEffect4.getDuration(), mapStatusEffect4.getAmplifier()));
                    }
                }
            }
        }
    }

}

之后我们需要在armor包中新建model包->model包中新建我们的盔甲的模型类ModelHeisensuit

ModelHeisensuit.java

package com.joy187.re8joymod.items.armor.model;

import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.items.armor.HeisensuitArmorItem;

import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib3.model.AnimatedGeoModel;


public class ModelHeisensuit extends AnimatedGeoModel<HeisensuitArmorItem> {

    //盔甲模型文件地址
    @Override
    public ResourceLocation getModelLocation(HeisensuitArmorItem object) {
        return new ResourceLocation(Main.MOD_ID, "geo/heisensuit.geo.json");
    }

    //盔甲材质文件地址
    @Override
    public ResourceLocation getTextureLocation(HeisensuitArmorItem object) {
        return new ResourceLocation(Main.MOD_ID, "textures/models/armor/heisensuit_layer_1.png");
    }

    //盔甲动画文件地址
    @Override
    public ResourceLocation getAnimationFileLocation(HeisensuitArmorItem animatable) {
        return new ResourceLocation(Main.MOD_ID, "animations/heisensuit.animation.json");
    }
}

之后我们需要在armor包中新建render包->render包中新建我们的盔甲的模型类ModelHeisensuit

``

package com.joy187.re8joymod.items.armor.render;

import com.joy187.re8joymod.items.armor.HeisensuitArmorItem;
import com.joy187.re8joymod.items.armor.model.ModelHeisensuit;

import software.bernie.geckolib3.renderers.geo.GeoArmorRenderer;


public class RenderHeisensuit extends GeoArmorRenderer<HeisensuitArmorItem> {
    //渲染盔甲穿在身上的每一个部位的效果
    public RenderHeisensuit() {
        super(new ModelHeisensuit());

        //这里要和第二步你blockbench中建模的名称一一对应
        this.headBone = "Head";
        this.bodyBone = "chestplate";
        this.rightArmBone = "rightArm";
        this.leftArmBone = "leftArm";
        this.rightLegBone = "rightLeg";
        this.leftLegBone = "leftLeg";
        this.rightBootBone = "rightBoot";
        this.leftBootBone = "leftBoot";
    }
}

4.在ClientModEventSubscriber类中将我们的盔甲渲染类进行注册:

ClientModEventSubscriber.java

@Mod.EventBusSubscriber(modid = Main.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ClientModEventSubscriber extends ModEventSubscriber{

    @OnlyIn(Dist.CLIENT)
    @SubscribeEvent
    public static void registerRenderers(final EntityRenderersEvent.AddLayers event) {

        //渲染类进行注册
        GeoArmorRenderer.registerArmorRenderer(HeisensuitArmorItem.class, new RenderHeisensuit());
    }
}

5.在ItemInit类中将我们的盔甲进行声明,盔甲属性请参考之前的教程1.18.2 盔甲套装

ItemInit.java

    //头盔
    public static final RegistryObject<HeisensuitArmorItem> HEISEN_HEAD = ITEMS.register("heisenhead",
            () -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.HEAD, new Item.Properties()));
    //胸甲
    public static final RegistryObject<HeisensuitArmorItem> HEISEN_SUIT = ITEMS.register("heisensuit",
            () -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.CHEST, new Item.Properties()));
    //护腿
    public static final RegistryObject<HeisensuitArmorItem> HEISEN_LEGG = ITEMS.register("heisenlegg",
            () -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.LEGS, new Item.Properties()));
    //靴子
    public static final RegistryObject<HeisensuitArmorItem> HEISEN_BOOTS = ITEMS.register("heisenboots",
            () -> new HeisensuitArmorItem(CustomArmorMaterial.ARMOR_MATERIAL_HEISENSUIT, EquipmentSlot.FEET, new Item.Properties()));

6.代码部分结束,之后来到材质包制作环节:

resources\assets\你的modid中的lang包中的en_us.json添加盔甲的英文名称:

  "item.re8joymod.heisenhead":"H",
  "item.re8joymod.heisensuit":"H",
  "item.re8joymod.heisenlegg":"Hei",
  "item.re8joymod.heisenboots":"Heis",

models\item包中添加所有盔甲的模型文件:

头盔

heisenhead.json

{
    "parent": "item/generated",
    "textures": {
        "layer0": "re8joymod:item/heisenhead"
    }
}

胸甲

heisensuit.json

{
    "parent": "item/generated",
    "textures": {
        "layer0": "re8joymod:item/heisensuit"
    }
}

护腿

heisenlegg.json

{
    "parent": "item/generated",
    "textures": {
        "layer0": "re8joymod:item/heisenlegg"
    }
}

靴子

heisenboots.json

{
    "parent": "item/generated",
    "textures": {
        "layer0": "re8joymod:item/heisenboots"
    }
}

textures\item中添加盔甲的手持贴图:

crr2.jpg

textures\models\armor中添加盔甲的穿戴后贴图:

crr3.jpg

assets\minecraft\textures\models\armor中同样添加我们的穿戴后贴图:

crr4.jpg

新建一个geo包和animation包,把第二步中的模型和动画文件分别放进去

cr10.png

8.保存所有文件 -> 进行测试:

穿上盔甲,如果可以正常显示,就说明我们成功了!

suiton.png




GRID
12天前

题目描述

给你一个 m * n 的矩阵 mat,以及一个整数 k ,矩阵中的每一行都以非递减的顺序排列。
你可以从每一行中选出 1 个元素形成一个数组。返回所有可能数组中的第 k 个 最小 数组和。

m == mat.length
n == mat.length[i]
1 <= m, n <= 40
1 <= k <= min(200, n ^ m)
1 <= mat[i][j] <= 5000
mat[i] 是一个非递减数组

输入格式

首先输入矩阵mat的行列数m和n
然后输入m行,每行n个非负整数,表示mat的元素值,以空格分隔。
最后输入k。

输出格式

输出一个整数,表示结果。

输入样例1

2 3
1 3 11
2 4 6
5

输出样例1

7

解释:从每一行中选出一个元素,前 k 个和最小的数组分别是:
[1,2], [1,4], [3,2], [3,4], [1,6]。其中第 5 个的和是 7 。

输入样例2

2 3
1 1 10
2 2 9
7

输出样例2

12

分析

由于题目说明每行都是呈现一个非递减序,所以我们可以得知矩阵的第一列的和一定为最小和,最后一列一定为最大和。
之后我们通过二分求出第k个大小的和即可。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
    int kthSmallest(vector<vector<int>>& mat, int k) {
        int n=mat.size(),m=mat[0].size();
        int l=0,r=0;
        for(int i=0;i<n;i++) l+=mat[i][0],r+=mat[i][m-1];   //求出一开始的最大最小和
        while(l<r)
        {
            int mid=(l+r)>>1;   
            int co=dfs(mat,mid,0,0,k);  //第co小的数组和为mid
            if(co>=k) r=mid; //如果比第k个要大,说明答案在左边,更新r=mid
            else l=mid+1;   //否则在右边,更新l
        }
        return r;
    }

    //统计数组和为target是矩阵中第几小的和
    int dfs(vector<vector<int>>& mat,int target,int row,int sum,int k)
    {
        if(row==mat.size()) return 1;   //走到了最后一行,说明找到了一个合法方案
        int ans=0;
        for(int i=0;i<mat[0].size();i++)    //第row行的每一列都进行枚举相加
        {
            int t=sum+mat[row][i];
            if(t<=target)   
            {
                int co=dfs(mat,target,row+1,t,k-ans);   //枚举下一行,更新当前和sum,以及需要再搜到k-ans个
                ans+=co;
                if(ans>k || !co) break; //如果已经比k大了或者上一轮没找到,就跳出循环               
            }
        }
        return ans;
    }
};
int main()
{

    int m, n,data,k;
    vector<vector<int> > mat;
    cin>>m>>n;

    for(int i=0; i<m; i++)
    {

        vector<int> row;

        for(int j=0; j<n; j++)
        {
            cin>>data;
            row.push_back(data);
        }
        mat.push_back(row);
    }
    cin>>k;
    int res=Solution().kthSmallest(mat,k);
    cout<<res<<endl;

    return 0;
}



GRID
13天前

题目描述

给定一个化学式formula(作为字符串),返回每种原子的数量。
原子总是以一个大写字母开始,接着跟随0个或任意个小写字母,表示原子的名字。
如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如,H2O 和 H2O2 是可行的,但 H1O2 这个表达是不可行的。
两个化学式连在一起是新的化学式。例如 H2O2He3Mg4 也是化学式。
一个括号中的化学式和数字(可选择性添加)也是化学式。例如 (H2O2) 和 (H2O2)3 是化学式。
给定一个化学式,输出所有原子的数量。格式为:第一个(按字典序)原子的名子,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。

输入格式

输入一个字符串,中间不包含空格

输出格式

输出一个字符串,表示结果。

输入样例1

H2O

输出样例1

H2O

解释:
原子的数量是 {‘H’: 2, ‘O’: 1}。

输入样例2

K4(ON(SO3)2)2

输出样例2

K4N2O14S4

解释:
原子的数量是 {‘K’: 4, ‘N’: 2, ‘O’: 14, ‘S’: 4}。


分析

本题目要求我们求出一个化学式的所有元素出现的总次数,并输出字典序。其做法和3284. 化学方程式方法类似。
考虑到化学式中存在()这样的括号结构,我们立刻想到使用将括号中的元素进行存储,之后计算括号外的系数,乘上后得到括号内每个元素的数量,以此类推。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
class Solution {
public:
    string countOfAtoms(string formula) {
        formula="("+formula+")"; //我们可以一开始给整个化学式套上一层括号
        string ans="";
        stack<pair<string,int> > stk;   //设置一个栈,元素是pair<元素名称,个数>
        int len=formula.size(),i=0;
        while(i<len)
        {
            if(formula[i]=='(') //遇到左括号就入栈
            {
                stk.push({"(",-1});
                i++;
            }
            else if(formula[i]==')')    //遇到右括号
            {
                i++;
                int co=1,temp=0;    //计算括号外系数
                while(i<len && formula[i]>='0' && formula[i]<='9')  
                {
                    temp=temp*10+(formula[i++]-'0');
                }
                if(temp) co=temp;

                vector<pair<string,int> > tmp;
                while(stk.size() && stk.top().first!="(")   //把栈中的元素都乘以系数,直到左括号停止
                {
                    tmp.push_back({stk.top().first,stk.top().second * co});
                    stk.pop();
                }
                stk.pop();

                for(auto item:tmp)  //将所有的临时数组中的元素加入到栈中
                    stk.push(item);
            }
            else{   //遇到的字符为字母
                if(formula[i]>='A' && formula[i]<='Z')
                {
                    string name=""; 
                    name+=formula[i++];
                    if(i<len && formula[i]>='a' && formula[i]<='z') //得到该化学元素名称
                    {
                        name+=formula[i++];
                    }                    

                    int co=1,temp=0;
                    while(i<len && formula[i]>='0' && formula[i]<='9')  //得到该化学元素的出现次数
                    {
                        temp=temp*10+(formula[i]-'0');
                        i++;
                    }
                    if(temp) co=temp;
                    stk.push({name,co});
                }

            }
        }
        map<string,int> mp; 
        while(stk.size())   //求出每种化学元素出现的总次数
        {
            // cout<<stk.top().first<<" "<<stk.top().second<<endl;
            mp[stk.top().first]+=stk.top().second;  
            stk.pop();
        }

        for(auto item:mp)   //输出答案
        {
            if(item.second==1) ans+=item.first;
            else ans+=item.first+to_string(item.second);
            //cout<<item.first<<" "<<item.second<<endl;
        }

        return ans;
    }
};

int main()
{
    string s; 
    cin>>s;

    cout<<Solution().countOfAtoms(s);
    return 0;

}



GRID
14天前

题目描述

一个整数区间 [a, b]  ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b。

给你一组整数区间intervals,请找到一个最小的集合 S,使得 S 里的元素与区间intervals中的每一个整数区间都至少有2个元素相交。

输出这个最小集合S的大小。

输入格式

首先输入intervals 的区间个数m(范围为[1, 3000]),
然后输入m行,每行2个数字( [0, 10^8]范围内的整数),表示区间的左、右边界。

输出格式

输出一个整数

输入样例

4
1 2
2 3
2 4
4 5

输出样例

5

分析

本题是区间选点的升级版,但是核心思想是一样的。
cr.jpg

我们给数组排序时,应该先按照右端点从小到大排,左端点从大到小排,之后遍历整个数组,判断左右端点关系。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
struct node{
  int l,r;

  bool operator<(const node &p) const{
      if(r!=p.r) return r<p.r;
      return l>p.l;
  }
};
class Solution {
public:
    int intersectionSizeTwo(vector<vector<int>>& intervals) {
        vector<node> v;
        for(auto item:intervals)
            v.push_back({item[0],item[1]});
        sort(v.begin(),v.end());
        vector<int> se;
        se.push_back(-1);   //这个数组用来存放所有的选取的端点,我们一开始插入一个边界点-1
        int len=v.size(),ans=0;
        for(auto t:v)
        {
            if(t.l>se[ans]) //当前区间左端点比集合中右端点大,就插入两个元素
            {
                se.push_back(t.r-1);
                se.push_back(t.r);
                ans+=2;
            }
            else if(t.l>se[ans-1]){ //当前区间左端点等于集合右端点,就插入一个元素
                se.push_back(t.r);
                ans++;
            }
        }

        return ans;
    }
};
int main()

{

    int m,n,data;

    vector<vector<int> > intervals;

    cin>>m;

    for(int j=0; j<m; j++)

    {

        vector<int> aRow;

        for(int i=0; i<2; i++)

        {

            cin>>data;
            aRow.push_back(data);
        }

        intervals.push_back(aRow);

    }



    int res=Solution().intersectionSizeTwo(intervals);
    cout<<res;


    return 0;

}




GRID
14天前

题目描述

给定一个已排序的正整数数组 nums,和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中,使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。

样例输入1

2
1 3
6

样例输出1

1

解释:
根据 nums 里现有的组合 [1], [3], [1,3],可以得出 1, 3, 4。
现在如果我们将 2 添加到 nums 中, 组合变为: [1], [2], [3], [1,3], [2,3], [1,2,3]。
其和可以表示数字 1, 2, 3, 4, 5, 6,能够覆盖 [1, 6] 区间里所有的数。
所以我们最少需要添加一个数字。

样例输入2

3
1 5 10
20

样例输出2

2

分析

我们需要使用到贪心的方法,假设当前我们能覆盖的范围是[1,miss),那么如果此时我们数组中的nums[i]≤miss的话,加入之后我们就可以覆盖[1,miss+nums[i])的范围;如果当前的元素不能凑出miss的话我们根据贪心的原理就让其加上一个miss,这样我们就可以把miss给凑合出来了。以这样的策略我们最终添加的数量是最少的。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
class Solution {
public:
    int minPatches(vector<int>& nums, int n) {
        long long miss=1,i=0,ans=0;
        int len=nums.size();
        while(miss<=n){
            if(i<len && nums[i]<=miss)
                miss+=nums[i++];
            else{
                miss+=miss;
                ans++;
            }
        }
        return ans;
    }
};
int main()
{
    cin>>m;
    vector<int> v;
    for(int i=0,a=0;i<m;i++)
    {
         cin>>a;
         v.push_back(a);
    }
    cin>>n;
    cout<<Solution().minPatches(v,n);
    return 0;

}



GRID
14天前

我们今天尝试对原版中的一些生物的掉落物进行修改

1.我们本次修改的是原版中Zombie的掉落物,所以我们需要找到原版Zombie的战利品表:

zombie.json

{
  "type": "minecraft:entity",
  "pools": [
    {
      "rolls": 1.0,
      "bonus_rolls": 0.0,
      "entries": [
        {
          "type": "minecraft:item",
          "functions": [
            {
              "function": "minecraft:set_count",
              "count": {
                "type": "minecraft:uniform",
                "min": 0.0,
                "max": 2.0
              },
              "add": false
            },
            {
              "function": "minecraft:looting_enchant",
              "count": {
                "type": "minecraft:uniform",
                "min": 0.0,
                "max": 1.0
              }
            }
          ],
          "name": "minecraft:rotten_flesh"
        }
      ]
    },
    {
      "rolls": 1.0,
      "bonus_rolls": 0.0,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:iron_ingot"
        },
        {
          "type": "minecraft:item",
          "name": "minecraft:carrot"
        },
        {
          "type": "minecraft:item",
          "functions": [
            {
              "function": "minecraft:furnace_smelt",
              "conditions": [
                {
                  "condition": "minecraft:entity_properties",
                  "predicate": {
                    "flags": {
                      "is_on_fire": true
                    }
                  },
                  "entity": "this"
                }
              ]
            }
          ],
          "name": "minecraft:potato"
        }
      ],
      "conditions": [
        {
          "condition": "minecraft:killed_by_player"
        },
        {
          "condition": "minecraft:random_chance_with_looting",
          "chance": 0.025,
          "looting_multiplier": 0.01
        }
      ]
    }
  ]
}

战利品的基本参数

          "type": "item",
          "name": "minecraft:gold_nugget",  # 掉落物的具体名称
          "weight": 5,  # 掉落权重
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 0,   # 一次最少掉几个
                "max": 2    # 一次最多掉几个
              }
            }

2.找到模组的资源包,在src\main\resources\data下新建minecraft包->在minecraft包中新建loot_tables包->在loot_tables包中新建entities包->在entities包中新建我们的zombie.json文件:

cr1.jpg
zombie.json

{
"type": "minecraft:entity",
  "pools": [
    {
      "name": "main",
      "rolls": 1,
      "entries": [
        {
          "type": "item",
          "name": "minecraft:gold_nugget",
          "weight": 5,
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 2
              }
            }
          ]
        },
        {
          "type": "item",
          "weight": 5,
          "name": "minecraft:diamond",
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 2
              }
            }
          ]
        },
        {
          "type": "item",
          "weight": 3,
          "name": "minecraft:iron_ingot",
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 1,
                "max": 1
              }
            }
          ]
        },
        {
          "type": "item",
          "weight": 5,
          "name": "minecraft:emerald",
          "functions": [
            {
              "function": "set_count",
              "count": {
                "min": 2,
                "max": 3
              }
            }
          ]
        }
      ]
    }
  ]
}

3.进入游戏调试:

我们给zombie设置为掉落钻石、绿宝石、铁锭等物品:
2022-07-25_19.08.06.png

击杀后掉落情况:

2022-07-25_19.08.22.png

所有掉落物都出现了,符合预期!




GRID
15天前

题目描述

给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。

一个子序列是从原始数组挑选一部分(也可以全部)元素而不改变相对位置形成的新数组

如果可以完成上述分割,则返回 true ;否则,返回 false 。

说明:

输入的数组长度范围为 [1, 10000]

输入样例1

8
1 2 3 3 4 4 5 5

输出样例1

true

解释:

你可以分割出这样两个连续子序列 :
1, 2, 3

3, 4, 5

输入样例2

6
1 2 3 4 4 5

输出样例2

false

分析

本题目采取贪心的思路,我们首先用一个哈希表mp1记录所有数字出现的次数,之后用另外一个哈希表mp2来表示长度至少为3的序列的是否存在。
如果当前数为x,如果mp2[x-1]存在,就把这个数接到x-1后面,同时更新mp2中以x-1结尾和以x结尾的序列个数。
若x-1的序列不存在,就重新开一个序列,但需要判断x+1,x+2是否存在。

C++ 代码

#include<bits/stdc++.h>
using namespace std;
int n;
class Solution {
public:
    bool isPossible(vector<int>& nums) {
        map<int,int> mp1,mp2;
        for(auto x:nums) mp1[x]++;  //记录所有数字的出现次数
        for(auto x:nums)
        {
            if(!mp1[x]) continue;   //如果这个数用完了,就跳过本轮循环
            if(mp2[x-1]){   //如果以x-1的序列存在,就把x加到末尾
                mp2[x]++;
                mp2[x-1]--;
                mp1[x]--;
            }
            else if(mp1[x+1] && mp1[x+2])   //若x-1的序列不存在,就重新开一个序列,但需要判断x+1,x+2是否存在
            {
                mp2[x+2]++; //创建一个以x开头,x+2结尾的序列
                mp1[x]--,mp1[x+1]--,mp1[x+2]--;
            }
            else return false;
        }
        return true;
    }
};
int main()
{

    cin>>n;
    vector<int> v;
    int a;
    for(int i=0;i<n;i++)
    {
        cin>>a;
        v.push_back(a);
    }

    if(Solution().isPossible(v)) puts("true");
    else puts("false");

    return 0;

}



GRID
1个月前

本次我将1.18.2的模组内容与1.16.5进行了同步。

1.故事书

玩家可以使用腐败草或者黑色羽毛加上一本书来合成该物品:

cr3.png

本书共分为序章、家族图鉴、病毒、末章四个篇章:

cr4.png

玩家可根据该书籍的内容合成想要的物品,挑战各种Boss。

2.新武器

本次增加了2把狙击枪和2把突击步枪以及对应的弹药。

cr5.png

F2 狙击枪、SA110 狙击枪

使用狙击枪弹药,玩家按‘F’键装备至副手时进入开镜模式。
注:F2可直接工作台购买,SA110需要找到公爵进行交易获得。

WCX 突击步枪,Dragoon突击步枪

使用步枪弹药,玩家按‘F’键装备至副手时进入开镜模式。按下‘Shift’键进入自动开火模式。

本次也为之前所有的枪械增加了开镜效果,均为‘F’键装备至副手时开镜。

cr6.png

3.其他

1.修改了公爵的商店内容,新增了步枪子弹和狙击枪子弹的交易。
2.修改了板条箱的随机掉落物品,增加了子弹掉落的概率。
3.增加了E病毒对与其他生物的互动效果。

百度网盘生化8模组

网盘密码:j7uj




GRID
1个月前

题目描述

给你一个链表的头节点 head,请你编写代码,反复删去链表中由总和值为 0 的连续节点组成的序列,直到不存在这样的序列为止。如果存在多个总和值为0的连续节点序列,优先删除位置靠前的序列。

删除完毕后,请你返回最终结果链表的头节点。

输入样例

[1,2,-3,3,1]

输出样例

[3,1]

分析

本题目要求我们将链表中连续的总和为0的串从链表中删除掉,为此可以先用一个前缀和数组对链表的元素和进行计算。之后我们从后枚举找到最长的和为0的串然后将其删除掉。

C++ 代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeZeroSumSublists(ListNode* head) {
        if(!head) return head;
        auto dummy=new ListNode(-1);
        dummy->next=head;
        int s[1010],idx=1;  //前缀和数组
        for(int i=0;i<1010;i++) s[i]=0;
        for(auto p=head;p;p=p->next)
        {
            s[idx]=p->val+s[idx-1];
            idx++;
        }
        idx--;
        auto p=dummy;
        int i=0;
        while(p)
        {
            int cur=s[i],f=0;   //当前前缀和为cur
            for(int j=idx;j>=i+1;j--)   //从后枚举找到一个和当前cur相等的前缀和,这就说明区间[i,j]内元素和为0
            {
                if(cur==s[j])
                {
                    f=j-i;
                    i=j+1;
                    break;
                }                
            }
            if(f)
            {

                auto q=p;
                for(int j=0;j<f+1;j++)  //q是把[i,j]区间隔过去后的第一个节点
                {
                    q=q->next;
                }             
                if(q) p->next=q;
                else{
                    p->next=NULL;
                }
                p=q;
            }
            else{   //没有找到相同的前缀和,就判断下一个节点
                p=p->next;
                i++;
            }
        }
        return dummy->next;
    }
};



GRID
1个月前

题目描述

给你一个头结点为 head 的单链表和一个整数 k ,请你设计一个算法将链表分隔为 k 个连续的部分。

每部分的长度应该尽可能的相等:任意两部分的长度差距不能超过 1 。这可能会导致有些部分为 null 。

这 k 个部分应该按照在链表中出现的顺序排列,并且排在前面的部分的长度应该大于或等于排在后面的长度。

返回一个由上述 k 部分组成的数组。

cr.png

输入样例

3
1 2 3
5

输出样例

head-->1-->tail
head-->2-->tail
head-->3-->tail
head-->tail
head-->tail

分析

采用贪心的思想:
如果元素个数小于分组个数,那么就把前面的组各放一个,后面都留空。
如果元素个数多于分组个数,那么就取余数,前面余数个组里面的元素比后面多1即可。

C++ 代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    vector<ListNode*> splitListToParts(ListNode* root, int k) {
        vector<ListNode*> ans(k);
        if(!root) return ans;
        //填充本函数完成功能  
        int tot=0;
        auto p=root;
        //求链表总长
        while(p){
            tot++;
            p=p->next;
        }
        //若元素数小于组数
        if(tot<=k)
        {
            int idx=0;
            while(root)
            {
                auto p=new ListNode(root->val);
                ans[idx]=p;
                idx++;
                root=root->next;
            }
        }
        else{
            //若元素数大于组数,每组有partlen个元素,有more组的元素个数为partlen+1
            int partlen=tot/k;
            int more=tot%k;
            int idx=0,partidx=1,thislen;
            while(root)
            {
                if(more>0) thislen=partlen+1;
                else thislen=partlen;
                auto tmp=new ListNode(-1),q=tmp;
                for(int i=0;i<thislen;i++)
                {
                    auto p=new ListNode(root->val);
                    q->next=p;
                    q=p;
                    root=root->next;
                }
                if(partidx<thislen) more--;
                ans[idx]=tmp->next;
                idx++;
            }
        }
        return ans;
    }
};