Jumping Machine (思维+01背包)

Jumping Machine
Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 megabytes
Young inventor has created a new jumping machine. In order to test it, he brought it to the testing
polygon. The polygon is an infinite square grid.
Initially, the machine is located in the cell (0, 0). The machine has n springs, the i-th spring has the force
of li and allows the machine to jump li cells up or li cells to the right. Therefore this spring allows the
machine to get from cell (x, y) either to cell (x + li
, y), or to cell (x, y + li). After jumping, the spring is
thrown back and cannot be reused. The machine can use the springs in any order.
During the tests the cells, that the machine will fly over, will be stained with machine oil. In order not
to clean the grid after himself, the inventor has decided to put a protective mat on each cell the machine
could potentially fly over.
Now the inventor is wondering how many protective mats he needs to bring to the test with him.
Input
The first line of input contains n — the number of springs that the machine has (1 ≤ n ≤ 100). The
second line contains n integers li — the springs forces (li ≥ 1; 1 ≤ l1 + l2 + · · · + ln ≤ 106
).
Output
Output a single integer: the number of mats that inventor needs to bring.
Example
standard input
2
4 2
standard output
22
Explanation
All the cells that can get dirty when the machine jumps in the example test are colored orange one the
figure below
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;

unordered_map<int, int> ma;
int n, l[N], dp[N], sum1[N];
vector<int> s;
int main() {
    ios::sync_with_stdio(false);
    cin >> n;
    LL sum = 0, i, j;
    for (i = 1; i <= n; i++) {
        cin >> l[i];
        sum += l[i];
    }
    dp[0] = 1;
    for (i = 1; i <= n; i++) {
        for (j = sum; j >= l[i]; j--) {
            if (dp[j - l[i]] && dp[j] == 0) {
                dp[j] = 1;
                s.push_back(j);
            }
        }
    }
    sort(s.begin(), s.end());
    int len = s.size();
    for (i = 0; i < len; i++) {
        ma[s[i]] = i + 1;
    }
    LL ans = 2 * sum + 1;
    for (i = 1; i < sum; i++) {
        if (dp[i]) {
            ans += sum - i;
        }
    }
    for (i = 1; i < sum; i++) {  //两个for循环可以合并,但我感觉这样写好理解
        if (dp[i]) {
            ans += i - ma[i];
        }
    }
    cout << ans << '\n';
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值