A - Changing Volume

题意:有个遥控器,有+1-1+2-2+5-5,6个键,不允许把音量调整至负数(当音量<5,则无法按-5),求最少按键使得a变成b。

题解:一开始以为音量<5按-5会变成0,这样要多一个特判。由于给的数字的缘故,并不会有穿过去然后反过来减掉更优的,比如+4不需要+5-1,直接+2+2。所以直接模拟。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

void test_case() {
    int a, b;
    scanf("%d%d", &a, &b);
    if(a > b)
        swap(a, b);
    printf("%d\n", (b - a) / 5 + ((b - a) % 5 + 1) / 2);
}

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t = 1;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        //printf("Case #%d: ", ti);
        test_case();
    }
}

B - Fridge Lockers

题意:有个n点m边无向图,每个点是冰箱,每条边是一种锁,要求安排一种方法使得每个点的锁不被另一个点的锁覆盖。

题解:原本m可以>n,这题就很复杂了,应该就把多出来的边换掉一最昂贵的边,意思是取出目前最贵的一组(u,v),然后连边(x,u),(x,v),这样就消费掉1条边且只增加了2x,当x取最小值时,比每次取出最小的(x,y)增加的x+y要便宜。但是这样贪心是不是有漏洞就不得而知了。现在规定m<=n,很显然不被另一个锁覆盖的意思就是要连至少两条边,且两条边连去不同的点。这样有解的时候当n>2且m=n时,方法是连成一个环。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

void test_case() {
    int n, m;
    scanf("%d%d", &n, &m);
    bool suc = (m == n && n > 2);
    int sum = 0;
    for(int i = 1, x; i <= n; ++i) {
        scanf("%d", &x);
        sum += x;
    }
    if(!suc) {
        puts("-1");
        return;
    }
    printf("%d\n", 2 * sum);
    for(int i = 1; i <= n - 1; ++i)
        printf("%d %d\n", i, i + 1);
    printf("%d %d\n", n, 1);
}

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t = 1;
    scanf("%d", &t);
    for(int ti = 1; ti <= t; ++ti) {
        //printf("Case #%d: ", ti);
        test_case();
    }
}
01-13 05:48