topcoder srm 590 div1

problem1 link

对于每一个,找到其在目标串中的位置,判断能不能移动即可。

problem2 link

如果最后的$limit$为$11=(1011)_{2}$,那么可以分别计算值为$(1011)_{2},(1010)_{2},(100x)_{2},(0xxx)_{2}$的答案数,$x$位置表示可以为任意。也就是可以忽略这些位。

当答案固定时,可以用高斯消元求解。

problem3 link

令$d(i,j)$表示点 $i$到点$j$的距离。

使用最小割求解。将每个点拆成$n$个点,第$i$个点拆成$p(i,0),p(i,1),...,p(i,n-1)$.其中$p(i,j)$如果与源点在一个割集,说明$d(0,i)\leq j$为假,与汇点在一个割集说明$d(0,i)\leq j$为真。

所以,如果一个割产生在边$p(i,j-1)\rightarrow p(i,j)$说明最后$d(0,i)=j$.其中边$p(i,j-1)\rightarrow p(i,j)$的代价为$(want[i]-j)^{2}$

有以下边:

(1)对于0点来说,$p(0,0)$与汇点的边流量为无穷大,说明,最后它与汇点在一个割集,所以$d(0,0)\leq 0$为真;

(2)对于$1\leq i < n$号点来说,源点到$p(i,0)$为无穷大(一定不可能),$p(i, n-1)$到汇点为无穷大(一定为真); $p(i,j-1)\rightarrow p(i,j),1\leq j < n)$为$(want[i]-j)^{2}$

(3)如果原来存在边$i\rightarrow j$,那么$p(i,k)\rightarrow p(j,k-1)$为无穷大,表示如果$d(0,i)>k$,那么一定有$d(0,j)>k-1$

code for problem1

#include <string>

class FoxAndChess {
 public:
  std::string ableToMove(const std::string &begin, const std::string &target) {
    int n = static_cast<int>(begin.size());
    int idx = 0;
    for (int i = 0; i < n; ++i) {
      if (begin[i] == ‘L‘ || begin[i] == ‘R‘) {
        while (idx < n && target[idx] == ‘.‘) {
          ++idx;
        }
        if (idx == n || begin[i] != target[idx] ||
            (begin[i] == ‘L‘ && i < idx) || (begin[i] == ‘R‘ && i > idx)) {
          return "Impossible";
        }
        ++idx;
      }
    }
    while (idx < n && target[idx] == ‘.‘) {
      ++idx;
    }
    if (idx != n) {
      return "Impossible";
    }
    return "Possible";
  }
};

code for problem2

#include <vector>

class XorCards {
 public:
  long long numberOfWays(const std::vector<long long> &number,
                         long long limit) {
    const int n = 52;
    const int m = static_cast<int>(number.size());
    long long result = 0;
    auto GetBit = [](long long t, int b) -> int {
      return (t & (1ll << b)) != 0 ? 1 : 0;
    };
    {
      std::vector<std::vector<int>> g(n, std::vector<int>(m + 1, 0));
      for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
          g[i][j] = GetBit(number[j], i);
        }
        g[i][m] = GetBit(limit, i);
      }
      result += Gauss(g);
    }
    for (int i = 0; i < n; ++i) {
      if (GetBit(limit, i) == 0) {
        continue;
      }
      std::vector<std::vector<int>> g(n, std::vector<int>(m + 1, 0));
      for (int j = i; j < n; ++j) {
        for (int k = 0; k < m; ++k) {
          g[j][k] = GetBit(number[k], j);
        }
        if (j > i) {
          g[j][m] = GetBit(limit, j);
        }
      }
      result += Gauss(g);
    }
    return result;
  }

 private:
  long long Gauss(std::vector<std::vector<int>> &g) {
    int n = static_cast<int>(g.size());
    int m = static_cast<int>(g[0].size()) - 1;
    int col = 0;

    auto HasBit = [&](int start, int col) {
      for (int i = n - 1; i >= start; --i) {
        if (g[i][col] != 0) return i;
      }
      return -1;
    };
    int row_number = 0;
    for (int i = 0; i < n && col < m; ++i) {
      int row = HasBit(i, col);
      while (row == -1 && col + 1 < m) {
        row = HasBit(i, ++col);
      }
      if (row == -1) {
        break;
      }
      if (row != i) {
        std::swap(g[i], g[row]);
      }
      for (int idx = 0; idx < n; ++idx) {
        if (idx != i && g[idx][col] != 0) {
          for (int k = 0; k <= m; ++k) {
            g[idx][k] ^= g[i][k];
          }
        }
      }
      ++col;
      ++row_number;
    }
    for (int i = row_number; i < n; ++i) {
      if (g[i][m] != 0) {
        return 0;
      }
    }
    if (m < row_number) {
      return 0;
    }
    return 1ll << (m - row_number);
  }
};

code for problem3

#include <limits>
#include <unordered_map>
#include <vector>

template <typename FlowType>
class MaxFlowSolver {
  static constexpr FlowType kMaxFlow = std::numeric_limits<FlowType>::max();
  static constexpr FlowType kZeroFlow = static_cast<FlowType>(0);
  struct node {
    int v;
    int next;
    FlowType cap;
  };

 public:
  int VertexNumber() const { return used_index_; }

  FlowType MaxFlow(int source, int sink) {
    source = GetIndex(source);
    sink = GetIndex(sink);

    int n = VertexNumber();
    std::vector<int> pre(n);
    std::vector<int> cur(n);
    std::vector<int> num(n);
    std::vector<int> h(n);
    for (int i = 0; i < n; ++i) {
      cur[i] = head_[i];
      num[i] = 0;
      h[i] = 0;
    }
    int u = source;
    FlowType result = 0;
    while (h[u] < n) {
      if (u == sink) {
        FlowType min_cap = kMaxFlow;
        int v = -1;
        for (int i = source; i != sink; i = edges_[cur[i]].v) {
          int k = cur[i];
          if (edges_[k].cap < min_cap) {
            min_cap = edges_[k].cap;
            v = i;
          }
        }
        result += min_cap;
        u = v;
        for (int i = source; i != sink; i = edges_[cur[i]].v) {
          int k = cur[i];
          edges_[k].cap -= min_cap;
          edges_[k ^ 1].cap += min_cap;
        }
      }
      int index = -1;
      for (int i = cur[u]; i != -1; i = edges_[i].next) {
        if (edges_[i].cap > 0 && h[u] == h[edges_[i].v] + 1) {
          index = i;
          break;
        }
      }
      if (index != -1) {
        cur[u] = index;
        pre[edges_[index].v] = u;
        u = edges_[index].v;
      } else {
        if (--num[h[u]] == 0) {
          break;
        }
        int k = n;
        cur[u] = head_[u];
        for (int i = head_[u]; i != -1; i = edges_[i].next) {
          if (edges_[i].cap > 0 && h[edges_[i].v] < k) {
            k = h[edges_[i].v];
          }
        }
        if (k + 1 < n) {
          num[k + 1] += 1;
        }
        h[u] = k + 1;
        if (u != source) {
          u = pre[u];
        }
      }
    }
    return result;
  }

  MaxFlowSolver() = default;

  void Clear() {
    edges_.clear();
    head_.clear();
    vertex_indexer_.clear();
    used_index_ = 0;
  }

  void InsertEdge(int from, int to, FlowType cap) {
    from = GetIndex(from);
    to = GetIndex(to);
    AddEdge(from, to, cap);
    AddEdge(to, from, kZeroFlow);
  }

 private:
  int GetIndex(int idx) {
    auto iter = vertex_indexer_.find(idx);
    if (iter != vertex_indexer_.end()) {
      return iter->second;
    }
    int map_idx = used_index_++;
    head_.push_back(-1);
    return vertex_indexer_[idx] = map_idx;
  }

  void AddEdge(int from, int to, FlowType cap) {
    node p;
    p.v = to;
    p.cap = cap;
    p.next = head_[from];
    head_[from] = static_cast<int>(edges_.size());
    edges_.emplace_back(p);
  }

  std::vector<node> edges_;
  std::vector<int> head_;

  std::unordered_map<int, int> vertex_indexer_;
  int used_index_ = 0;
};

#include <string>

class FoxAndCity {
 public:
  int minimalCost(const std::vector<std::string> linked,
                  const std::vector<int> want) {
    constexpr int kMaxCapacity = 1000000;
    int n = static_cast<int>(linked.size());
    MaxFlowSolver<int> solver;
    auto Index = [&](int u, int k) { return u * n + k; };
    int source = -1;
    int sink = -2;
    for (int i = 0; i < n; ++i) {
      if (i == 0) {
        solver.InsertEdge(Index(i, 0), sink, kMaxCapacity);
        continue;
      }

      solver.InsertEdge(source, Index(i, 0), kMaxCapacity);
      solver.InsertEdge(Index(i, n - 1), sink, kMaxCapacity);
      for (int j = 1; j < n; ++j) {
        solver.InsertEdge(Index(i, j - 1), Index(i, j),
                          (want[i] - j) * (want[i] - j));
      }
    }
    for (int i = 0; i < n; ++i) {
      for (int j = 0; j < n; ++j) {
        if (linked[i][j] == ‘Y‘) {
          for (int k = 1; k < n; ++k) {
            solver.InsertEdge(Index(i, k), Index(j, k - 1), kMaxCapacity);
          }
        }
      }
    }
    return solver.MaxFlow(source, sink);
  }
};

原文地址:https://www.cnblogs.com/jianglangcaijin/p/9384937.html

时间: 2024-10-10 00:47:37

topcoder srm 590 div1的相关文章

Topcoder SRM 643 Div1 250&lt;peter_pan&gt;

Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*......*pn,我们假设p0,p1,...,pn是单调不降的,那么v里存储的是下标为偶数 的N的质因数p0,p2,p4,...,p(2k).现在要求写一个程序,返回一个vector<long long>ans; ans里存储的是p0,p1,p2,...,pn. Limits Time Limit(m

Topcoder SRM 648 Div1 250

Problem 给一个长度为N的"AB"字符串S,S只含有两种字符'A' 或 'B',设pair(i,j)(0=<i<j<N)表示一对 i,j 使得S[i]='A',S[j]='B'.现给定一个K,求字符串S,使得pair(i,j)的个数恰好为K.若不存在,则返回空串. Limits Time Limit(ms): 2000 Memory Limit(MB): 256 N: [2, 50] K: [0 , N*(N-1)/2 ] Solution 若K>(N/2

Topcoder SRM 627 div1 HappyLettersDiv1 : 字符串

Problem Statement      The Happy Letter game is played as follows: At the beginning, several players enter the field. Each player has a lowercase English letter on their back. The game is played in turns. In each turn, you select two players with dif

SRM 590 DIV1

转载请注明出处,谢谢viewmode=contents">http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 水水更健康,最终回到1800+了... DIV2 1000pt 显然每一列是独立的.分开考虑. 对于某一列.假设按单个字符U , D从下往上考虑的话.发现连续两个U的话.以下的U能够移动的位置受上面一个影响. 只是因此能够想到相邻的U , D互相限制位置,能够依次处理.相邻同样字符的话. 能够作为一个字符

topcoder srm 738 div1 FindThePerfectTriangle(枚举)

Problem Statement      You are given the ints perimeter and area. Your task is to find a triangle with the following properties: The coordinates of each vertex are integers between 0 and 3000, inclusive. The perimeter of the triangle must be exactly

Topcoder SRM 603 div1题解

昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点,每个节点都有一个权值,两人A和B分别进行操作,由A先手,每人可以选择一条边,将它删掉得到两个联通块.游戏不断进行下去,最后只剩下一个节点.A希望最后的节点权值尽可能大,B希望尽可能小,求这个最后的值.数据保证n<=50. 这道题真的是博弈好题啊-(感觉放到ACM很合适啊) 我们考虑第一次A会如何选

topcoder srm 320 div1

problem1 link 两个数字后面都有阶乘符号,可以抵消. import java.util.*; import java.math.*; import static java.lang.Math.*; public class ExtraordinarilyLarge { public String compare(String x, String y) { boolean both=false; while(x.endsWith("!")&&y.endsWit

topcoder srm 712 div1 -23

1.给定两个长度为$n$的数组$A,B$.有两种操作可以作用于数组$A$.第一种,将每个元素左侧的相邻数字加到其上:第二种,将每个元素右侧的相邻数字加到其上.0的左侧是$n-1$,$n-1$的右侧是0.比如1,2,3,4执行第一种操作后是5,3,5,7.给出一个不超过100的操作序列使得$A$变成$B$.$n \leq 50$. 思路:将$a_{0},a_{1},...,a_{n-1}$看做$a_{0}x^{0}+a_{1}x^{1}+...+a_{n-1}x^{n-1}$.那么第一种操作相当于

Topcoder SRM 345 Div1 250

题意:起初在(0,0),要到(x,y)去,每次只能横向或纵向移动.横向移动时,若所在直线y为偶数,那么只能往x轴正方向移动,若为奇数,只能往x轴反方向移动:纵向移动时,若所在直线x为偶数,那么只能往y轴正方向移动,若为奇数,只能往y轴反方向移动.问从起点到终点的最短距离是多少? x,y 范围是[-1e6, 1e6] 解法:一开始想到bfs(想到很自然),将(0, 0), (x, y), (x, 0), (0, y)这4个点分别周围9个点(包括自己)作为可达点.bfs处理出(0, 0)到(x, y