topcoder srm 525 div1

problem1 link

最后剩下的是中间的一个矩形.所以可以直接枚举这个矩形,如果它含有的硬币个数等于$K$,则再计算移动的最少次数,更新答案.

problem2 link

首先,每个节点发送每种消息最多只发送一次;其次,在得到消息之后一定是马上发送而不是等待一会儿再发送;最后一点是,如果第$i$天发送了一种消息,一定可以在第$i+1$天发送另外一种消息.

现在的问题是,一个节点同时有两种消息时,应该首先发送哪一种.这个可以$2^{n}$枚举第一次发送的消息类型,然后模拟即可.在模拟过程中可能会出现先来的消息不是枚举的第一次发送的类型.这个可以直接结束这种情况,因为一定会枚举到一种情况,其他节点都一样,而这个节点是先发送另一种状态.

problem3 link

首先,如果将给出的矩阵看作是$n$个顶点的有向图,那么交换$i,j$行列得到的新图相当于两个顶点交换标号,即顶点$i$变为$j$,顶点$j$变为$i$.

那么题目就是要对给出的图重新标号,使得与目标图匹配.

对于$n=8$来说,如果画出目标图,是下面的样子:

设$p_{i}$表示目标图的第$i$个顶点是原图的第$p_{i}$个顶点.那么对于$n=8$来说,确定了$p_{0},p_{1},p_{n-1}$后,与$p_{1}$相连且不与$p_{n-1}$相连的就是$p_{2}$,同时与$p_{1}$和$p_{n-1}$相连的是$p_{6}$.

也就是说由$p_{1},p_{7}$可找到$p_{2},p_{6}$.同理,由$p_{2},p_{6}$可找到$p_{3},p_{5}$,最后就是$p_{4}$.查找的过程如下图所示(第一幅图找到$p_{2},p_{6}$,第二幅图找到$p_{3},p_{5}$)

最后一个问题就是如果有了这个数组$p$,求最少的交换次数.$p$中的数组组成了若干个环,对于每个环$C$,需要的交换次数为$|C|-1$

 

code for problem1

#include <vector>
#include <string>
#include <algorithm>
using namespace std;

class DropCoins {
  public:
    int getMinimum(vector <string> board, int K) {
      const int n = (int)board.size();
      const int m = (int)board[0].size();
      int result = -1;
      vector<vector<int>> f(n + 1, vector<int>(m + 1, 0));
      for (int i = 1; i <= n; ++ i) {
        for (int j = 1; j <= m; ++ j) {
          f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1];
          if (board[i - 1][j - 1] == 'o') {
            ++ f[i][j];
          }
        }
      }
      for (int left = 1; left <= m; ++ left) {
        for (int right = left; right <= m; ++ right) {
          for (int up = 1; up <= n; ++ up) {
            for (int down = up; down <= n; ++ down) {
              int cnt = f[down][right] - f[down][left - 1] - f[up - 1][right]
                + f[up - 1][left - 1];
              if (cnt == K) {
                int cost = Cost(left - 1, m - right) + Cost(up - 1, n - down);
                if (result == -1 || result > cost) {
                  result = cost;
                }
              }
            }
          }
        }
      }
      return result;
    }

  private:
    int Cost(int x, int y) {
      return std::min(x + x + y, x + y + y);
    }
};

code for problem2

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Rumor {
  public:
  int getMinimum(string knowledge, vector<string> graph)
  {
    const int n = (int)graph.size();
    int result = -1;
    for (int mask = 0; mask < (1 << n); ++ mask) {
      int cost = calculate(mask, knowledge, graph);
      if (cost != -1 && (result == -1 || result > cost)) {
        result = cost;
      }
    }
    return result;
  }

  private:

  int getFirstType(int mask, int i) {
    return (mask & (1 << i)) ? 2 : 1;
  }
  int getSecondType(int mask, int i) {
    return (mask & (1 << i)) ? 1 : 2;
  }
  int calculate(const int mask, const string& knowledge, 
      const vector<string>& graph) {
    const int n = (int)knowledge.size();
    long long preGetMessageState = 0;
    long long currentKnowMessageState = 0;
    int preBroadcastMask = 0;
    int day = 0;
    for (int i = 0; i < n; ++ i) {
      if (knowledge[i] == 'Y') {
        preGetMessageState |= 3ll << (i << 1);
      }
    }
    int sendedMessageMask = 0;
    currentKnowMessageState = preGetMessageState;
    const long long finalState = (1ll << (n + n)) - 1;
    while (currentKnowMessageState != finalState) {
      ++ day;
      int nowBroadcastState = 0;
      long long nowGetMessageState = 0;
      for (int i = 0; i < n; ++ i) {
        int type = -1;
        if (preBroadcastMask & (1 << i)) {
          type = getSecondType(mask, i);
        }
        else if (!(sendedMessageMask & (1 << i))) {
          int t = (preGetMessageState >> (i + i)) & 3;
          if (t != 0) {
            if (t & getFirstType(mask, i)) {
              type = getFirstType(mask, i);
            }
            else {
              return -1;
            }
          }
        }
        if (type == -1) {
          continue;
        }
        for (int j = 0; j < n; ++ j) {
          if (graph[i][j] == 'Y') {
            nowGetMessageState |= ((long long)type) << (j + j);
          }
        }
        if (type == getSecondType(mask, i)) {
          sendedMessageMask |= 1 << i;
        }
        else {
          nowBroadcastState |= 1 << i;
        }
      }
      long long currentAll = currentKnowMessageState | nowGetMessageState;
      if (currentAll == currentKnowMessageState) {
        return -1;
      }
      currentKnowMessageState = currentAll;
      preGetMessageState = nowGetMessageState;
      preBroadcastMask = nowBroadcastState;
    }
    return day;
  }
};

code for problem3

#include <vector>
#include <string>
#include <algorithm>
using namespace std;


class MonochromePuzzle {
  public: 
    int getMinimum(vector <string> board) {
      const int n = (int)board.size();
      for (int i = 0; i < n; ++ i) {
        int cnt = 0;
        for (int j = 0; j < n; ++ j) {
          if (board[i][j] == '#') {
            ++ cnt;
          }
        }
        if (cnt != 3) {
          return -1;
        }
      }
      int result = -1;
      for (int i = 0; i < n; ++ i) {
        for (int j = 0; j < n; ++ j) {
          if (i == j) {
            continue;
          }
          for (int k = 0; k < n; ++ k) {
            if (k == i || k == j) {
              continue;
            }
            if (board[i][j] != '#' || board[i][k] != '#') {
              continue;
            }
            int tmp = calculate(i, j, k, board);
            if (tmp != -1 && (result == -1 || result > tmp)) {
              result = tmp;
            }
          }
        }
      }
      return result;
    }
  private:
    int calculate(const int p0, const int p1, const int p2,
        const vector<string>& board) {
      const int n = (int)board.size();
      vector<int> p(n, 0);
      vector<int> used(n, 0);
      p[0] = p0;
      p[1] = p1;
      p[n - 1] = p2;
      used[p0] = used[p1] = used[p2] = 1;
      int x = 1, y = n - 1;
      int a = 2, b = n - 2;
      while (a < b) {
        int ta = -1, tb = -1;
        for (int i = 0; i < n; ++ i) {
          if (used[i] == 0 && board[p[x]][i] == '#') {
            if (board[p[y]][i] == '#') {
              tb = i;
            }
            else {
              ta = i;
            }
          }
        }
        if (ta == -1 || tb == -1) {
          return -1;
        }
        p[a] = ta;
        p[b] = tb;
        used[ta] = used[tb] = 1;
        x = a ++;
        y = b --;
      }
      for (int i = 0; i < n; ++ i) {
        if (used[i] == 0 && board[p[x]][i] == '#' && 
            board[p[y]][i] == '#' && board[p[n - 1]][i] == '#') {
           p[a] = i;
           return getCost(p);
        }
      }
      return -1;
    }
    int getCost(const vector<int>& p) {
      const int n = (int)p.size();
      vector<int> visited(n, 0);
      int result = n;
      for (int i = 0; i < n; ++ i) {
        if (visited[i]) {
          continue;
        }
        int current = i;
        while (visited[current] == 0) {
          visited[current] = 1;
          current = p[current];
        }
        result -= 1;
      }
      return result;
    }
};

  

posted @ 2018-01-27 18:04  朝拜明天19891101  阅读(293)  评论(0编辑  收藏  举报