首页 > 试题广场 >

积木

[编程题]积木
  • 热度指数:1560 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
小易有堆积木,第堆积木有块。小易还拥有一个容量无限的背包。
一开始小易站在第一堆积木旁边。每次小易可以选择进行下列三种操作中的一种:
1、从背包里掏出一块积木(如果有的话)放到当前这一堆里
2、从当前这一堆积木里掏出一块塞到背包里(如果当前积木堆不为空的话)
3、从当前这一堆走到下一堆。
一开始小易的背包里有块积木。小易希望把这些个积木变成严格递增的(即。小易希望知道这是否有可能能完成。(所有操作结束后不需要保证背包里没有积木了,可以有积木堆为空)。

输入描述:
第一行数据组数T
对于每组数据,第一行数字,接下来一行个数字表示.



输出描述:
对于每组数据输出一行,输出结果YES或NO
示例1

输入

1
5 3
2 2 3 3 1

输出

YES
示例2

输入

1
5 2
0 0 1 2 1

输出

NO
所有的积木都按照0,1,2,3...这样排,所以只需要判断到第i个积木时,前面i个积木堆加上背包里的m大于等于i*(i+1)/2就行了
T =int(input())
for t in range(T):
    nm =[int(n) for n in input().split()]
    n =nm[0]
    m =nm[1]
    h =[int(n) for n in input().split()]
    number =m
    result =True
    for i in range(n):
        number =number+h[i]
        if(number<(i*(i+1)/2)):
            result =False
            break
    if(result ==True):
        print("YES")
    else:
        print("NO")
发表于 2020-03-27 18:02:41 回复(2)
这题描述不是贼烂??只能从这三种选择里选的话,拿或者放了一个就不能走了?(意味着我只能改动一次)。。。如果说是拿或者放一个还能走。。示例1都过不了。。。。
1
5 3
2 2 3 3 1
比如
1,2,3,3,1 。m=4
1,2,3,3,1。m=4
1,2,3,4,1。m=3
1,2,3,4,4。m=0
最后一个无论如何你都搞不了。。。
实际上题目的意思是拿或者放了可以不走,继续拿或者放(实际就是你能无限拿,无限放。)。。。。
noOfdata = int(input())
for _ in range(noOfdata):
    n, m = map(int, input().split(' '))
    items = list(map(int, input().split(' ')))
    m += items[0]
    items[0] = 0 
    prevItem = items[0]
    ok = True
    for idx in range(1, len(items)):
        if items[idx] > idx:
            m += items[idx] - idx
            items[idx] = idx
        elif items[idx] == idx:
            prevItem = items[idx]
        elif items[idx] < idx:
            placeItems = idx - items[idx]
            if m >= placeItems:
                m -= placeItems
                items[idx] = idx
            else:
                ok = False
                break
    if ok:
        print("YES")
    else:
        print("NO")




发表于 2020-02-27 13:55:23 回复(4)
将积木调整为0,1,2,3,...,当第i堆积木大于i时,从堆中拿积木放入包里;当第i堆积木小于i时,从背包里拿出积木放入堆中,如果在进行这个操作时没包里有积木了,就无法完成,直接返回NO。如果遍历完之后都没有跳出,则表示可以完成,返回YES。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        while(T-- >0){
            int n = sc.nextInt(), m = sc.nextInt();
            int[] arr = new int[n];
            for(int i = 0; i < n; i++) arr[i] = sc.nextInt();
            System.out.println(solve(arr, m));
        }
    }
    
    // 为了留下的积木少,积木堆就按照0,1,2,...的方式排
    private static String solve(int[] arr, int m) {
        boolean flag = true;
        long bagHeapNum = m;
        for(int i = 0; i < arr.length; i++){
            if(arr[i] > i) {
                bagHeapNum += arr[i] - i;
            }else if(arr[i] < i){
                if(bagHeapNum >= i - arr[i])
                    bagHeapNum -= i - arr[i];
                else
                    return "NO";
            }
            arr[i] = i;        // 这一句可写可不写,因为并不需要返回调整后的积木堆数组,只要知道能否调整即可
        }
        return "YES";
    }
}


发表于 2020-10-22 15:57:16 回复(0)
T = int(input())
for _ in range(T):
    n, m = map(int, input().split())
    h = list(map(int, input().split()))
    for i in range(n):
        put = i - h[i]
        m -= put
        if m < 0:
            print('NO')
            break
        h[i] += put
    if i == n-1:
        print('YES')

发表于 2020-08-07 20:15:56 回复(0)
T = int(input())
def get(m, n, h):
    for i in range(n):
        if h[i] == i:continue
        if h[i] > i:
            m += h[i] - i
        else:
            if m >= i - h[i]:
                m -= i - h[i]
            else:
                return False
    return True
for _ in range(T):
    n, m = map(int, input().split())
    h = list(map(int, input().split()))
    res = get(m, n, h)
    if res:
        print('YES')
    else:
        print('NO')

发表于 2020-04-24 14:59:17 回复(0)
其实最简单的积木堆为0,1,2,3,4,。。。
既然背包容量无限大,只要把家积木调成这个,即h【i】=i,当走到一堆积木,此时背包里的积木不够把积木的个数变成i时,此时就不能满足条件了,输出即可
var shunum = readline()
for (let i = 0;i<shunum;i++){
    for (let j=2*i;j<=2*i+1;j++){
        var a = readline().split(' ')
        var h =[]
        if((j+2)%2 == 0){
            n=parseInt(a[0])
            k=parseInt(a[1])
        }else{
            for (let m=0;m<a.length;m++){
                h[m]=parseInt(a[m])
            }
        }
    }
    main(k,h)
}
function main(k,h){
    var bag = k
    var success = true
    for (let p =0;p<h.length;p++){//循环积木堆的长度
        if (h[p]>p){
            bag = bag + h[p]-p
        }else{
            if(bag >=(p-h[p])){
                bag = bag-(p-h[p])
            }else{
                success = false
                continue
            }
        }
    }
    if(success == false){
        return console.log('NO')
    }else{
        return console.log('YES')
    }
}


发表于 2020-02-21 17:55:37 回复(4)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();
        for (int i = 0; i < t; i++) {
            Integer n = scanner.nextInt();
            Long m = scanner.nextLong();
            long[] arr = new long[n];
            for (int i1 = 0; i1 < n; i1++) {
                arr[i1] = scanner.nextLong();
            }
            System.out.println(demo4(m, arr));
        }
    }
    public static String demo4(long m, long[] arr) {

        long sum1 = 0;//最苛刻的数量
        long sum2 = m;//当前总数量
        for (int i = 0; i < arr.length; i++) {
            sum1 += i;
            sum2 += arr[i];
            if (sum2 < sum1) {
                return "NO";
            }
        }
        return "YES";
    }
}
发表于 2020-08-04 23:19:58 回复(0)
import java.util.Scanner;

/**
 * 小易有n堆积木,第i堆积木有h{i}块。小易还拥有一个容量无限的背包。
 * 一开始小易站在第一堆积木旁边。每次小易可以选择进行下列三种操作中的一种:
 * 1、从背包里掏出一块积木(如果有的话)放到当前这一堆里
 * 2、从当前这一堆积木里掏出一块塞到背包里(如果当前积木堆不为空的话)
 * 3、从当前这一堆走到下一堆。
 * 一开始小易的背包里有m块积木。小易希望把这些个积木变成严格递增的(即h_{1} < h_{2} < h_{3} \dots < h_{n}h1
 * 。小易希望知道这是否有可能能完成。(所有操作结束后不需要保证背包里没有积木了,可以有积木堆为空)。
 */
public class Question18 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        scanner.useDelimiter("\n");
        int nums = scanner.nextInt();
        while (nums > 0){
            String next = scanner.next();
            String[] split = next.split(" ");
            long m = Long.parseLong(split[1]);
            String value = scanner.next();
            new Question18().answer(m, value);
            nums--;
        }
    }

    /**
     * 如果每组积木可以按严格递增排序,输出true 否则输出false
     * @param m     书包中积木的数量
     * @param value 每组积木中每堆积木的数量
     */
    public void answer(long m, String value) {
        if (value.length() == 0){
            System.out.println("NO");
            return;
        }
        String result = "";
        boolean isAdd = true;
        String[] split = value.split(" ");
        for (int i = 0; i < split.length; i++) {
            long temp = Long.parseLong(split[i]);
            m = m + temp - i;
            if (m < 0) {
                result = "NO";
                isAdd = false;
                break;
            }
        }
        if (isAdd) {
            result = "YES";
        }
        System.out.println(result);
    }
}

发表于 2022-12-01 15:23:23 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        for(int i = 0; i < T;i++){
            int n = sc.nextInt();
            long m = sc.nextLong();
            long sum = 0L;
            long s = 0L;
            for(int j = 0; j < n;j++){
                sum += sc.nextLong();
                s += j;
                long need = s - sum;
                if(need > 0L)
                    m -= need;
            }
            if(m >= 0L)
                System.out.println("YES");
            else
                System.out.println("NO");
        }
    }
}有没有大佬帮忙看一下为什么只能过60%
发表于 2020-08-12 23:57:57 回复(0)
var num = parseInt(readline())
while(num--){
    var arr = readline().split(" ")
    var n = parseInt(arr[0])
    var k = parseInt(arr[1])
    var h = readline().split(" ")
    for(var i=0;i<n;i++){
        h[i] = parseInt(h[i])
    }
    print(main(k,h))
}
function main(k,h){
    var bag = k
    var success = true
    for(let p = 0;p<h.length;p++){
        if(h[p]>p){
            bag = bag + h[p] - p
        }else{
            if(bag >= (p-h[p])){
                bag = bag-(p-h[p])
            }else{
                success = false
                continue
            }
        }
    }
    if(success == false){
        return 'NO'
    }else{
        return 'YES'
    }
}


发表于 2020-08-08 13:54:58 回复(0)
「每次」小易可以选择进行下列三种操作中的「一种」
发表于 2020-08-08 10:40:27 回复(0)
Python解法 把所有积木按照0,1,2,3...这样排放,大于index的放入背包m中,小于index则从背包取出,如果发现背包里的积木不够弥补差值则返回NO。
def f(nums, m):
    m += nums[0]
    nums[0] = 0
    for j in range(1, len(nums)):
        if nums[j] > j:
            m += nums[j]-j
        elif nums[j] < j:
            if m >= j-nums[j]:
                m -= j-nums[j]
            else: return 'NO'
        nums[j] = j
    return 'YES'
                
T = int(input())
for i in range(T):
    n, m = map(int, input().split())
    nums = list(map(int, input().split()))
    print(f(nums, m))

发表于 2020-08-08 03:21:38 回复(0)
贪心,0,1,2,3...
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int t; cin>>t;
    while(t--){
    int n,m; cin>>n>>m;
    ll h;
    ll sum=m;
    int f=1;
    for(int i=0;i<n;i++){
        cin>>h;
        if(sum+h>=i) {
            sum=sum+h-i;
        }
        else {
            f=0;
        }
    }
    if(f==1) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    }
    return 0;
}


发表于 2020-07-15 23:09:37 回复(3)
T=int(input())
for _ in range(T):
    n,m=list(map(int,input().split()))
    arr=list(map(int,input().split()))
    for i in range(n):
        m+=arr[i]
        m-=i
        if m<0:
            print("NO")
            break
    else:print("YES")
发表于 2020-06-23 13:57:46 回复(0)
难点:理解题意,注意int溢出
#include<vector>
(721)#include<iostream>
using namespace std;

int main() {
	int lines;
	cin >> lines;
	while (lines-- > 0) {
		int n, m;
		cin >> n >> m;
		vector<int>nums(n);
		unsigned long long sum = m;
		for (int i = 0; i < nums.size(); ++i) 
			cin >> nums[i];
		bool flag = true;
		int max = n * (n - 1) / 2;
		for (int i = 0; i < nums.size(); ++i) {
			sum += nums[i];
			if (sum >= max)break;
			if (sum < i * (i + 1) / 2) {
				flag = false;
				break;
			}
		}
		
		cout << (flag ? "YES" : "NO") << endl;
	}
}


发表于 2020-05-13 10:46:17 回复(0)
题目描述的太有迷惑性了....参考了解答才懂
import sys
n = int(sys.stdin.readline().strip())
ns = []
ms = []
lists = []
for i in range(n):
    tmp = map(int, str(sys.stdin.readline().strip()).split())
    ns.append(tmp[0])
    ms.append(tmp[1])
    tmp = map(int, str(sys.stdin.readline().strip()).split())
    lists.append(tmp)
    
for i in range(n):
    hs = lists[i]
    N = ns[i]
    M = ms[i]
    
    M+=hs[0]
    hs[0] = 0
    flag = 1
    for j in range(1,N):
        M += hs[j] - j
        if M<0:
            print('NO')
            flag = 0
            break
    if flag:
        print('YES')



发表于 2020-04-06 21:31:33 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Long t = scanner.nextLong();
        for (int i = 0; i < t; i++) {
            Integer n = scanner.nextInt();
            Long m = scanner.nextLong();
            long[] arr = new long[n];
            for (int i1 = 0; i1 < n; i1++) {
                arr[i1] = scanner.nextLong();
            }
            System.out.println(demo4(m, arr));
        }
    }


    /**
     *
     *
     * @param m m代表书包中初始积木输血量
     * @param arr 代表n堆的积木数量
     * @return
     */
    public static String demo4(long m, long[] arr) {

        long sum1 = 0;
        long sum2 = 0;
        for (int i = 0; i < arr.length; i++) {
            //当前积木堆的最苛刻解数量总和即 0、1、2、3、4、5...
            sum1= (i * (i + 1)) / 2;
            //当前堆中的积木数量总和
            sum2 += arr[i];
            if (sum2 + m < sum1) {
                return "NO";
            }
        }
        return "YES";
    }
}

发表于 2020-04-05 17:48:34 回复(0)
t = int(input())
for _ in range(t):
    n, m = list(map(int, input().split()))
    li = list(map(int, input().split()))
    cur = m
    flag = True
    for i in range(n):
        if li[i] > i:
            cur += li[i] - i
        elif li[i] < i:
            if cur < i - li[i]:
                flag = False
                break
            cur -= i - li[i]
    if flag:
        print('YES')
    else:
        print('NO')

发表于 2020-04-04 13:20:56 回复(0)
贪心求解即可

#include <cstdio>
#include <cstring>
#include <algorithm>

#define MAX_N 100000+100
int T;
int N;
long long m;
int H[MAX_N];



int main()
{

	bool ok = true;

	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%lld", &N, &m);
		ok = true;
		for (int i = 0; i < N; i++)
		{
			scanf("%d", &H[i]);
		}
		long long cur = -1;
		for (int i = 0; i < N; i++)
		{
			cur++;
			if (cur - H[i] > m) { ok = false; break; }
			m += (long long) H[i] - cur;
		}
		if (ok)
			printf("YES\n");
		else
			printf("NO\n");
	}


	return 0;
}


发表于 2020-01-08 20:42:45 回复(0)
// 有疑问!选择第一第二种情况可以一直停留吗?还是执行完就到下一堆了?
            //通过测试可以知道。。可以一直停留的。。所以算法肯定要改
            var g_num=parseInt(readline());//组数
            while(g_num>0){
                g_num--;
                var arr=readline();
                var n=parseInt(arr.split(" ")[0]);//积木堆数
                var m=parseInt(arr.split(" ")[1]);//背包积木数
                var h_arr=readline().split(" ");// 积木数组
                h_arr.forEach((item,i)=>{
                    h_arr[i]=parseInt(item)
                })
                
                var t_h_arr=h_arr;//临时保存数组
                
                var min=0;//三种选择的依据之一,最小值
                for(var i=0;i<h_arr.length;i++){
                    //第一种情况, min<arr[i]<arr[i+1]
                    //此时要让arr[i]=min+1;
                    
                    if(i<n && h_arr[i]>min){
                        //刚好不等于+1
                        if(h_arr[i]!=min+1){
                            //拿走积木
                            var tem=min+1;
                            m=m+(h_arr[i]-min-1);
                            h_arr[i]=tem;//更改数组
                        }
                    }
                    // 第二种情况,min<arr[i],arr[i]>arr[i+1]
                    //此时让 min+1<=arr[i] arr[i]>=arr[i+1]-1;
                    //但是本质和第一种一样。。
                    
                    //第三种情况,arr[i]<=min
                    //此时 arr[i]=min+1;//判断m是否足够
                    else if(i<n && h_arr[i]<=min){
                        var tem=min+1-h_arr[i];//差值
                        //m足够,(h_arr[i]!=0 || i!=0)是为了排除索引为0时0的干扰
                        if(tem<=m && (h_arr[i]!=0 || i!=0)){
                            h_arr[i]=min+1;
                            m=m-tem;
                        }
                    }
                    min=h_arr[i];//更新最小值
                    // console.log(h_arr)
                }
                var r_num=0;
                for(var j=0;j<n;j++){
                    if(j<n-1 && h_arr[j]<h_arr[1+j]){
                        r_num++;//记录
                    }
                }
                // console.log(r_num)
                if(r_num==n-1){
                    print("YES")
                }else{
                    print("NO")
                }
            }
发表于 2019-12-24 00:11:42 回复(0)