TopCoder14580: EllysRPS

题意

yyb y y b 要去与 m m (m100)个人玩游戏
由于 yyb y y b 忙着切大火题,他没有太多的精力浪费在游戏上
所以仁慈的 yyb y y b 决定放 m m 个人一条生路,不吊打他们
然而yyb为了维护自己红太阳的形象,不能输,所以他希望与每个人玩游戏都能是平局

游戏很简单,就是石头剪刀布, yyb y y b 会与每个人玩 n(n20) n ( n ≤ 20 )
只要双方赢的次数相同就视为平局

yyb y y b 非常的强,所以大家每一场比赛想出什么 yyb y y b 一眼就看出来了
每个人的策略都是一个长度为 n n 的序列
然后他觉得能用同一个长度为n的策略序列与每个人打平局
然而 yyb y y b 并不满足与这些,他想知道自己有多少种方式打平,这样他就能知道别人比自己弱多少,从而增长自己的淫威

正如大家所知, yyb y y b 秒题入魔,懒得去想这个 naive n a i v e 的比赛
所以请比他弱的你来帮他求出这个方案数

Sol

meet in the midlle m e e t   i n   t h e   m i d l l e
爆搜,把状态开 vector v e c t o r 压进 map m a p 查询

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
typedef vector <int> vi;

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int win[3][3] = {{0, -1, 1}, {1, 0, -1}, {-1, 1, 0}};
int n, m, a[105][25], b[25], mid;
vi tmp;
map <vi, int> t;
ll ans;

IL void Record(){
    tmp.clear();
    for(RG int i = 1; i <= m; ++i){
        RG int cnt = 0;
        for(RG int j = 1; j <= mid; ++j) cnt += win[a[i][j]][b[j]];
        tmp.push_back(cnt);
    }
    ++t[tmp];
}

IL void Dfs1(RG int l){
    if(l > mid){
        Record();
        return;
    }
    for(RG int i = 0; i < 3; ++i) b[l] = i, Dfs1(l + 1);
}

IL void Calc(){
    tmp.clear();
    for(RG int i = 1; i <= m; ++i){
        RG int cnt = 0;
        for(RG int j = mid + 1; j <= n; ++j) cnt -= win[a[i][j]][b[j]];
        tmp.push_back(cnt);
    }
    ans += t[tmp];
}

IL void Dfs2(RG int l){
    if(l > n){
        Calc();
        return;
    }
    for(RG int i = 0; i < 3; ++i) b[l] = i, Dfs2(l + 1);
}

IL ll Solve(){
    mid = (1 + n) >> 1;
    Dfs1(1), Dfs2(mid + 1);
    return ans;
}

class EllysRPS{
public:
    ll getCount(vector <string> s){
        m = s.size(), n = s[0].size();
        for(RG int i = 1; i <= m; ++i)
            for(RG int j = 1; j <= n; ++j)
                if(s[i - 1][j - 1] == 'R') a[i][j] = 0;
                else a[i][j] = (s[i - 1][j - 1] == 'S') + 1;
        return Solve();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值