SRM710 div1 ReverseMancala(trick)

题目大意,

给定一个有n个点的环,n不超过10,每个点上有一个权重

起始时权重将会给出,然后有2种操作

第一种操作是,选择一个位置i,获得权重w = a[i],把a[i]变成0,然后接下来在环上顺着走,每个数都加1,直到w为0

第二种操作是,选择一个位置i,在换上倒着走,每个数都减去1,然后收集这个权重w,直到遇见0,然后把w填到0里

求一种方案,使得从起始的权重到达终止的权重

不难发现,这两种操作互为逆操作

所以只用第一种操作

先把起始权重全部集中到a[0]

终止权重也全部集中到a[0]

然后最终方案就是方案一加方案二的逆操作

orz

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef vector<int> VI;

VI solve(VI a){
    int n = a.size();
    int sum = 0;
    VI ans;
    for(auto x : a) sum += x;
    while(a[0] != sum){
        for(int i = 1; i < n; i++){
            while(a[i] != 0){
                ans.push_back(i);
                int p = (i+1)%n, t = a[i];
                a[i] = 0;
                while(t){
                    a[p]++;
                    t--;
                    p = (p+1)%n;
                }
            }
        }
    }
    return ans;
}

class ReverseMancala{
public:
    VI findMoves(VI a, VI b){
        VI x = solve(a);
        VI y = solve(b);
        VI z;
        int n = a.size();
        reverse(y.begin(), y.end());
        for(auto X : x) z.push_back(X);
        for(auto X : y) z.push_back(X+n);
        return z;
    }
};
原文地址:https://www.cnblogs.com/Saurus/p/7044347.html