牛客练习赛84 C 牛客推荐系统开发之选飞行棋子

牛客推荐系统开发之选飞行棋子

https://ac.nowcoder.com/acm/contest/11174/C

首先这题题型很DP,然后容易想到DP状态f[i][j]为前i个人用前j种棋子的方案数。
后来感觉状态转移不太好写(本人太菜),就把第一维改成了四个人有无使用棋子的状态压缩,状态转移就很显然了。
这里我用的是刷表法:
f[k][j+1] += f[i][j], 当且仅当:
1. 在二进制下,i为k的真子集,且仅有一个数位不同(令该位置为p,则k=i|1<<p)。
2. s[p][j+1] = '1'。
f[i][j+1] += f[i][j], 正常的转移。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAXN = 5e3 + 5;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
#define For(i, a, b) for (int i = (int)(a); i <= (int)(b); i++)
#define Rep(i, a, b) for (int i = (int)(a); i >= (int)(b); i--)
#define DEBUG(x) cout << (x) << '\n'
#define fi first
#define se second

int n;
char a[4][MAXN];
ll f[20][MAXN];
inline void run() {
  cin >> n;
  For(i, 0, 3) cin >> a[i] + 1;
  f[0][0] = 1; //初始化
  For(j, 0, n) For(s, 0, 15) {
    For(i, 0, 3)
      if(!(s&1<<i) && a[i][j+1]&1) 
        f[s|1<<i][j+1] += f[s][j];   //第一种转移
    f[s][j+1] += f[s][j];            //第二种转移
  } 
  DEBUG(f[15][n]);                   //15的二进制为1111,表示四个人都用了棋子
}
int main() {
#ifdef Irene
  freopen("input.txt", "r", stdin);
  freopen("output.txt", "w", stdout);
#endif // Irene
  ios_base::sync_with_stdio(false);
  cin.tie(0), cin.tie(0);

  // int T; for(cin >> T; T--;)
  run(); return 0;
}
全部评论

相关推荐

10-09 00:50
已编辑
长江大学 算法工程师
不期而遇的夏天:1.同学你面试评价不错,概率很大,请耐心等待;2.你的排名比较靠前,不要担心,耐心等待;3.问题不大,正在审批,不要着急签其他公司,等等我们!4.预计9月中下旬,安心过节;5.下周会有结果,请耐心等待下;6.可能国庆节前后,一有结果我马上通知你;7.预计10月中旬,再坚持一下;8.正在走流程,就这两天了;9.同学,结果我也不知道,你如果查到了也告诉我一声;10.同学你出线不明朗,建议签其他公司保底!11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
AFBUFYGRFHJLP:直接去美帝试试看全奖phd吧
点赞 评论 收藏
分享
评论
1
收藏
分享
牛客网
牛客企业服务