Competitive Programming: TopCoder – Marketing

[Link to problem]

Problem Statement

You work for a very large company that markets many different products. In some cases, one product you market competes with another. To help deal with this situation you have split the intended consumers into two groups, namely Adults and Teenagers. If your company markets 2 products that compete with each other, selling one to Adults and the other to Teenagers will help maximize profits. Given a list of the products that compete with each other, you are going to determine whether all can be marketed such that no pair of competing products are both sold to Teenagers or both sold to Adults. If such an arrangement is not feasible your method will return -1. Otherwise, it should return the number of possible ways of marketing all of the products.

The products will be given in a compete whose kth element describes product k. The kth element will be a single-space delimited list of integers. These integers will refer to the products that the kth product competes with. For example:

compete = {"1 4",
            "2",
            "3",
            "0",
	    ""}

The example above shows product 0 competes with 1 and 4, product 1 competes with 2, product 2 competes with 3, and product 3 competes with 0. Note, competition is symmetric so product 1 competing with product 2 means product 2 competes with product 1 as well.

Ways to market:

  1. 0 to Teenagers, 1 to Adults, 2 to Teenagers, 3 to Adults, and 4 to Adults
  2. 0 to Adults, 1 to Teenagers, 2 to Adults, 3 to Teenagers, and 4 to Teenagers

Your method would return 2.

Definition

Class: Marketing

Method: howMany

Parameters: String[]

Returns: long

Method signature: long howMany(String[] compete)

Constraints

  • compete will contain between 1 and 30 elements, inclusive.
  • Each element of compete will have between 0 and 50 characters, inclusive.
  • Each element of compete will be a single space delimited sequence of integers such that:
    • All of the integers are unique.
    • Each integer contains no extra leading zeros.
    • Each integer is between 0 and k-1 inclusive where k is the number of elements in compete.
  • No element of compete contains leading or trailing whitespace.
  • Element i of compete will not contain the value i.
  • If i occurs in the jth element of competej will not occur in the ith element of compete.

Examples

{"1 4","2","3","0",""}
Returns: 2
The example from above
{"1","2","0"}
Returns: -1
Product 0 cannot be marketed with product 1 or 2. Product 1 cannot be marketed with product 2.
There is no way to achieve a viable marketing scheme.
{"1","2","3","0","0 5","1"}
Returns: 2
{"","","","","","","","","","", "","","","","","","","","","", "","","","","","","","","",""}
Returns: 1073741824
{"1","2","3","0","5","6","4"}
Returns: -1

Solution below . . .

Solution

Graph represented as adjacency matrix. Depth-first search to find viable solutions. More comments included in the code.

import java.util.StringTokenizer;

public class Marketing {

  boolean productMatrix[][];
  char market[];
  int n;
  boolean impossible;

  public long howMany(String[] compete) {

    n = compete.length;

    productMatrix = new boolean[n][n];
    market = new char[n];

    // build the product matrix showing competing products
    for (int i = 0; i < compete.length; i++) {
      StringTokenizer st = new StringTokenizer(compete[i], " ");

      while (st.hasMoreTokens()) {
        int j = Integer.parseInt(st.nextToken());
        productMatrix[i][j] = productMatrix[j][i] = true;
      }
    }

    impossible = false;

    // market[i] is the target market (A or T) for product i.
    // initialize to empty
    for (int i = 0; i < n; i++)
      market[i] = 0;

    int choices = 0;

    for (int i = 0; i < n; i++)

      // any time we have a choice of which market to place a
      // product, increment a counter.
      if (market[i] == 0) {
        choices++;

        // depth-first search to see if the product can be
        // placed without conflict.
        dfs(i, 'A');
      }
    if (impossible)
      return -1;

    // every product for which we had a choice of placement
    // represents two different marketing outcomes.
    long ways = 1;
    while (choices-- > 0)
      ways *= 2;
    return ways;
  }

  // depth-first search
  void dfs(int u, char c) {

    // has a conflict arisen?
    if (market[u] != 0) {
      if (market[u] != c)
        impossible = true;
      return;
    }

    // if not, do a recursive dfs on competing products
    market[u] = c;
    for (int v = 0; v < n; v++)
      if (productMatrix[u][v])
        dfs(v, (c == 'A') ? 'T' : 'A');
  }

  public static void main(String[] args) {

    Marketing marketing = new Marketing();

    // Returns: 2
    System.out.println(
        marketing.howMany(new String[] {"1 4", "2", "3", "0", ""}));

    // Returns: -1
    // Product 0 cannot be marketed with product 1 or 2.
    // Product 1 cannot be marketed with product 2.
    // There is no way to achieve a viable marketing scheme.
    System.out.println(marketing.howMany(new String[] {"1", "2", "0"}));

    // Returns: 2
    System.out.println(
        marketing.howMany(new String[] {"1", "2", "3", "0", "0 5", "1"}));

    // Returns: 1073741824
    System.out.println(marketing.howMany(new String[] {"", "", "", "", "",
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
        "", "", "", "", "", "", "", ""}));

    // Returns: -1
    System.out.println(marketing
        .howMany(new String[] {"1", "2", "3", "0", "5", "6", "4"}));

  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *