首页 > 试题广场 >

时津风的资源收集

[编程题]时津风的资源收集
  • 热度指数:1366 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
{\hspace{15pt}}时津风曾沉迷于页游 Kancolle。在游戏中,有一项日常任务需要玩家使用油、弹药、钢材、铝这 4 种资源来开发装备。
{\hspace{15pt}}现给定目标资源量 a,b,c,d,时津风进入开发界面时 4 种资源均为 10 单位。她可以对单一资源执行以下任意一种操作(资源总量始终保持在区间 [10,300]):
{\hspace{23pt}}\bullet\,将该资源 \pm 1
{\hspace{23pt}}\bullet\,将该资源 \pm 10
{\hspace{23pt}}\bullet\,将该资源 \pm 100
{\hspace{23pt}}\bullet\,直接将该资源设为上限 300
{\hspace{23pt}}\bullet\,直接将该资源设为下限 10

{\hspace{15pt}}在保证所有资源始终处于合法范围的前提下,求使四种资源同时恰好达到 (a,b,c,d) 所需的最少操作次数。

输入描述:
{\hspace{15pt}}第一行输入整数 T\left(1\leqq T\leqq 10^{5}\right) —— 测试组数。
{\hspace{15pt}}接下来 T 行,每行输入 4 个整数 a,b,c,d\ \left(10\leqq a,b,c,d\leqq 300\right)


输出描述:
{\hspace{15pt}}对每组数据输出一个整数,表示最少操作次数。
示例1

输入

2
10 100 200 300
10 10 10 10

输出

5
0

说明

样例1:

第一组测试数据,可能的操作是:

初始 [10,10,10,10]
将弹药增加 100,变成 [10,110,10,10]
将弹药减少 10,变成 [10,100,10,10]
将钢材增加到上限,变成 [10,100,300,10]
将钢材减少 100,变成 [10,100,200,10]
将铝增加到上限,变成 [10,100,200,300]

可以发现无法使用 5 次以下的操作来达到开发所需的资源量,所以答案为 5

第二组测试数据,开发所需的资源量就为资源初始值,所以不需要进行任何操作。
import sys

for line in sys.stdin:
    data = line.split()
    n = int(data[0])
    break

dp = [float("inf") for _ in range(301)]
dp[10] = 0
dp[300] = 1
operation = [1, -1, 10, -10, 100, -100]
count = 0
while float("inf") in dp:
    for i in range(301):
        if dp[i] == count:
            for op in operation:
                x = i + op
                if 0 <= x <= 300 and dp[x] == float("inf"):
                    dp[x] = count + 1
    count += 1

for line in sys.stdin:
    data = line.split()
    data = [int(x) for x in data]
    print(sum(dp[num] for num in data))

发表于 2026-03-12 22:23:31 回复(0)
from collections import deque
import sys

T = int(input().strip())

memo = [-1] * 301  # BFS先走完10-300的表,后续查表就行,不用每次都算
memo[10] = 0  # 前面 0-9 十个索引可以浪费,达到初始值直接查表目的
dq = deque([10])  # 题目初始值为10
while dq:
    cur = dq.popleft()
    # 同时满足加减和赋值
    for operation in [
        cur + 1, cur - 1, 
        cur + 10, cur - 10, 
        cur + 100, cur - 100, 
        300
    ]:
        # 得没修改过然后不越界才得到最少操作次数,这里防止memo[operation]索引越界才放后面
        if 10 <= operation <= 300 and memo[operation] == -1:
            dq.append(operation)
            memo[operation] = memo[cur] + 1

res = []
for line in sys.stdin:
    a, b, c, d = map(int, line.strip().split())
    res.append(memo[a] + memo[b] + memo[c] + memo[d])

sys.stdout.write('\n'.join(map(str, res)))

发表于 2026-03-05 11:12:54 回复(0)
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;
unordered_map<int, int>steps;//哈希表记录搜索过的数据
int bfs(int& aim, int begin) {
    if (steps[aim])return steps[aim];
    if (aim == begin)return 0;
    //暴力搜索
    queue<pair<int, int>>q;
    unordered_map<int, bool>hash;//减少重复搜索次数
    q.emplace(begin - 1, 1);
    q.emplace(begin + 1, 1);
    q.emplace(begin - 10, 1);
    q.emplace(begin + 10, 1);
    q.emplace(begin - 100, 1);
    q.emplace(begin + 100, 1);
    q.emplace(300, 1);
    while (!q.empty()) {
        int n = q.front().first;
        int step = q.front().second;
        q.pop();
        if (hash[n])continue;
        hash[n]=true;
        if (n == aim) {
            steps[aim] = step;
            return step;
        } else {
            if (n > aim) {
                q.emplace(n - 1, step + 1);
            }
            if (n < aim) {
                q.emplace(n + 1, step + 1);
            }
            if (n > aim) {
                q.emplace(n - 10, step + 1);
            }
            if (n < aim) {
                q.emplace(n + 10, step + 1);
            }
            if (n > aim) {
                q.emplace(n - 100, step + 1);
            }
            if (n < aim) {
                q.emplace(n + 100, step + 1);
            }
        }
    }
    return 0;
}

int main() {
    int T;
    cin >> T;
    int sum_steps = 0;
    for (int i = 0; i < T; i++) {
        vector<int>vi(4, 0);
        for (int i = 0; i < 4; i++) {
            cin >> vi[i];
            sum_steps += bfs(vi[i], 10);
        }
        cout << sum_steps << endl;
        sum_steps = 0;
    }
}
// 64 位输出请用 printf("%lld")
发表于 2026-02-19 22:48:41 回复(0)
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VAL 305 // 数值的合法范围是 10~300,数组开305足够覆盖 #define QUEUE_SIZE 10000 // 循环队列的最大容量,防止BFS过程中队列溢出 int step_mini[MAX_VAL]; // 存储每个数值从起点10到达的最小步数,-1表示不可达 int queue[QUEUE_SIZE]; // 用数组模拟循环队列,存储BFS过程中的数值节点 int q_front, q_rear; // 队列的头尾指针:front指向队首,rear指向队尾的下一个位置 int visited[MAX_VAL]; // 标记数值是否被访问过,0=未访问,1=已访问,替代C++的set // 操作函数:根据操作类型x,计算当前数值num执行操作后的结果 // x取值1~8对应8种不同操作 int op(int num, int x) { if (x == 1) return num + 1; // 操作1:数值+1 else if (x == 2) return num - 1; // 操作2:数值-1 else if (x == 3) return num + 10; // 操作3:数值+10 else if (x == 4) return num - 10; // 操作4:数值-10 else if (x == 5) return num + 100; // 操作5:数值+100 else if (x == 6) return num - 100; // 操作6:数值-100 else if (x == 7) return 300; // 操作7:直接将数值设为上限300 else if (x == 8) return 10; // 操作8:直接将数值设为下限10 else { printf("????"); // 异常操作类型,容错提示 return 1; } } // 循环队列的入队操作 void queue_push(int val) { // 判断队列是否已满:尾指针的下一个位置等于头指针则满 if ((q_rear + 1) % QUEUE_SIZE != q_front) { queue[q_rear] = val; // 将数值存入队尾 // 尾指针后移一位,取余实现循环(到队尾后回到队首) q_rear = (q_rear + 1) % QUEUE_SIZE; } } // 循环队列的出队操作,返回队首数值 int queue_pop() { int val = queue[q_front]; // 取出队首数值 // 头指针后移一位,取余实现循环 q_front = (q_front + 1) % QUEUE_SIZE; return val; } // 判断队列是否为空:头尾指针重合则为空 int queue_empty() { return q_front == q_rear; } // BFS核心函数:计算从起始数值start到所有合法数值的最小步数 // BFS按层级遍历,首次访问到数值的步数即为最小步数 void BFS(int start) { // 初始化队列头尾指针和访问标记数组 q_front = q_rear = 0; memset(visited, 0, sizeof(visited)); // 所有数值初始化为未访问 queue_push(start); // 起始数值入队,启动BFS visited[start] = 1; // 标记起始数值为已访问,防止重复入队 step_mini[start] = 0; // 起始数值到自身的步数为0 int step = 0; // 记录当前BFS的层级(步数) while (!queue_empty()) { // 队列不为空时持续遍历 // 计算当前层级的节点数量:处理完当前层所有节点,步数才+1 int sz = (q_rear - q_front + QUEUE_SIZE) % QUEUE_SIZE; // 遍历当前层级的所有节点 for (int k = 0; k < sz; k++) { int cur = queue_pop(); // 取出队首的当前数值 // 尝试对当前数值执行8种操作 for (int i = 1; i <= 8; i++) { int nex = op(cur, i); // 计算操作后的新数值 // 检查新数值是否合法:在10~300范围内 且 未被访问过 if (nex >= 10 && nex <= 300 && !visited[nex]) { visited[nex] = 1; // 标记为已访问 step_mini[nex] = step + 1; // 下一层级的步数=当前步数+1 queue_push(nex); // 新数值入队,参与下一层遍历 } } } step++; // 当前层级所有节点处理完毕,步数加1 } } int main() { // 初始化step_mini数组为-1,表示所有数值初始状态为不可达 memset(step_mini, -1, sizeof(step_mini)); // 起点数值为10,到自身的步数为0 step_mini[10] = 0; BFS(10); // 执行BFS,计算所有数值的最小步数 int T; scanf("%d", &T); // 读取测试用例组数 while (T--) { // 遍历每组测试用例 int sum = 0; // 存储4个资源的最小步数总和 int x; // 读取4个目标资源数值,累加对应的最小步数 for (int i = 0; i < 4; i++) { scanf("%d", &x); sum += step_mini[x]; } printf("%d\n", sum); // 输出每组的总步数 } return 0; } </string.h></stdlib.h></stdio.h>
发表于 2026-01-10 20:55:04 回复(0)
#include<bits/stdc++.h>
using namespace std;

#define all(a) a.begin(), a.end()
#define PII pair<int, int>
#define fi first
#define sc second
#define LL long long
#define vi vector<int>
#define vb vector<bool>
#define mk make_pair
#define IO ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
const int N = 1e5 + 5;
const int M = 2e5 + 5;
const int mod = 998244353;
const int Mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const LL inff = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
int n, m, k, t, T, _;

int step[310];
bool vis[310];

void init() {
    queue<int> q;
    q.push(10);
    q.push(300);
    step[300] = 1;
    vis[300] = 1;

    int dir[6] = {1, -1, 10, -10, 100, -100};

    while(q.size()) {
        int x = q.front();
        q.pop();

        for (int i = 0; i < 6; i++) {
            int j = x + dir[i];
            if (j > 10 && j <= 300 && !vis[j]) {
                vis[j] = 1;
                step[j] = step[x] + 1;
                q.push(j);
            }
        }
    }
}

void solve() {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    cout << step[a] + step[b] + step[c] + step[d] << endl;
}

int main(){
    init();
    for (cin >> _; _--;)
        solve();
    return 0;
}
发表于 2025-12-10 12:42:40 回复(0)
#include <iostream>
#include <queue>
#include <vector>
#include <set>
#include <unordered_map>
using namespace std;
vector<int> step_mini(305, -1);
int op(int num, int x) {
    if (x == 1) return num + 1;
    else if (x == 2) return num - 1;
    else if (x == 3) return num + 10;
    else if (x == 4) return num - 10;
    else if (x == 5) return num + 100;
    else if (x == 6) return num - 100;
    else if (x == 7) return 300;
    else if (x == 8) return 10;
    else{
        cout << "????";
        return 1;
    };
}
void BFS(int start) {
    queue<int> q;
    set<int> visited;

    int step = 0;
    q.push(start);
    visited.insert(start);
    while (!q.empty()) {
        int sz = q.size();
        for (int k = 0; k < sz; k++) {
            int cur = q.front();
            q.pop();
            for (int i = 1; i <= 8; i++) {
                int nex = op(cur, i);
                if (nex >= 10 && nex <= 300 && !visited.count(nex)) {
                    q.push(nex);
                    visited.insert(nex);
                    if(step_mini[nex] == -1)step_mini[nex] = step + 1;
                }
            }
        }
        step++;
    }
}
int main() {
    step_mini[10] = 0;
    int T;
    cin >> T;
    BFS(10);
    while (T--) {
        int sum = 0;
        for(int i = 0; i < 4; i++){
            int x;
            cin >> x;
            sum += step_mini[x];
        }
        cout << sum << endl;
    }
}
// 64 位输出请用 printf("%lld")
打表
发表于 2025-10-27 13:52:23 回复(0)
package main

import (
	"fmt"
)

type Node struct{
    value, step int
}

var result [301]int // 存储10到其他数值所需的操作次数
func BFS() { // 计算10到其他数值所需的操作次数
    for i:=0;i<=300;i++{
        result[i] = -1
    }
    queue := []Node{{10,0}}
    result[10]=0
    var cur Node
    var dist []int
    for len(queue) > 0{
        cur = queue[0]
        queue = queue[1:]

        dist = []int{
            cur.value-1,cur.value+1,
            cur.value+100,cur.value-100,
            cur.value+10, cur.value-10,
            10, 300,
        }
       
        for _, d := range dist {
            if d < 10 || d >300 || result[d] != -1{
                continue
            }
            result[d] = cur.step + 1
            queue = append(queue, Node{d, cur.step+1})
        }
    }
}

func main() {
    var a, b, c, d int
    var t int
    fmt.Scanf("%d", &t)
    BFS()
    for t >0 {
        t--
        fmt.Scanf("%d %d %d %d", &a, &b, &c, &d)
        
        fmt.Println(result[a]+result[b]+result[c]+result[d])
    }
}

发表于 2025-09-07 16:13:03 回复(0)