SRM710 div1 ReverseMancala(trick)

本文介绍了一种解决环形曼卡拉游戏问题的算法。游戏中玩家通过两种操作改变环上节点的权重,目标是从初始权重状态达到指定的目标状态。文章提供了一个C++实现的解决方案,该算法将操作简化并通过集中权重的方法找到最优路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意,

给定一个有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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值