【搜索+图论】TopCoder SRM 556 XorTravelingSalesman

来源:互联网 发布:linux 查看磁盘 编辑:程序博客网 时间:2024/06/06 03:27

又刷了一道500分的题目,感觉topCoder的题目质量真的很高,建模思想非常好。

Problem Statement

 Warning: This problem statement contains superscripts and/or subscripts. It may not display properly outside of the applet.

You are playing a video game similar to the famous traveling salesman problem. In this game, you travel between cities and collect profits according to some rules explained in the next paragraphs. Unlike the traditional traveling salesman problem, it is allowed to visit each of the cities multiple times.

There are N cities numbered 0 through N-1. Each city has an associated value. The values are given in vector <int>cityValues, wherecityValues[i] is the value of city i.

There are also zero or more bidirectional roads connecting the cities. Each road connects exactly two different cities and can be traversed in both ways. The information about the roads is given in vector <string>roads. The j-th character of the i-th element of roads will be 'N' if there is no road connecting city i and city j, or 'Y' if there is exactly one road connecting city i and city j.

In this game, you start at city 0 with profit cityValues[0]. Your goal is to maximize your final profit. At any time in the game, you may perform one of the following actions:

  • End the game. Your current profit will be recorded as your final profit.
  • Move to another city by traversing a single road. This is the interesting part of the game: assume that your current profit is P and the destination city is city X. After traversing the road, you will be at city X with profit P XORcityValues[X].

You are given the vector <int> cityValues and the vector <string>roads. Return the maximum possible final profit you can achieve in this game.

Definition

 Class:XorTravelingSalesmanMethod:maxProfitParameters:vector <int>, vector <string>Returns:intMethod signature:int maxProfit(vector <int> cityValues, vector <string> roads)(be sure your method is public)  

Notes

-If a and b are single bits then a XOR b is defined as (a + b) modulo 2. For two integers, A and B, in order to calculate A XOR B, they need to be represented in binary: A = (an...a1)2, B = (bn...b1)2 (if the lengths of their representations are different, the shorter one is prepended with the necessary number of leading zeroes). Then A XOR B = C = (cn...c1)2, where ci = ai XOR bi. For example, 10 XOR 3 = (1010)2 XOR (0011)2 = (1001)2 = 9.

Constraints

-cityValues will contain between 1 and 50 elements, inclusive.-Each element of cityValues will be between 0 and 1023, inclusive.-roads will contain exactly N elements, where N is the number of elements ofcityValues.-Each element of roads will contain exactly N characters, where N is the number of elements ofcityValues.-Each character in roads will be either 'N' or 'Y'.-For each i, the i-th character of the i-th element of roads will be 'N'.-For each pair (i, j), the j-th character of the i-th element of roads will be equal to the i-th character of the j-th element ofroads.

Examples

0)  
{0, 7, 11, 5, 2}
{"NYNYY", "YNYNN", "NYNNN", "YNNNN", "YNNNN"}
Returns: 14
One possible solution:
  • Start at city 0. Profit = cityValues[0] = 0.
  • Move to city 1. Profit = 0 XOR 7 = 7.
  • Move to city 2. Profit = 7 XOR 11 = 12.
  • Move to city 1. Profit = 12 XOR 7 = 11.
  • Move to city 0. Profit = 11 XOR 0 = 11.
  • Move to city 3. Profit = 11 XOR 5 = 14.
  • End the game.
1)  
{556}
{"N"}
Returns: 556
You cannot move anywhere.2)  
{0, 4, 8, 32, 512}
{"NYYYY", "YNNNN", "YNNNN", "YNNNN", "YNNNN"}
Returns: 556
  

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.     


我的程序(其实基本是抄标程,惭愧。。。。)

#include<iostream>#include<queue>#include<utility>#include<string>#include<vector>#include<string.h>#include<algorithm>using namespace std;class XorTravelingSalesman{public:int maxProfit(vector<int> cityValues, vector<string> roads){int n=cityValues.size();int result=-1;bool flag[55][1200];memset(flag,false,sizeof(flag));//pair<cityNumber,currentValue>queue<pair<int,int> > q;while(q.empty()==false)q.pop();q.push(make_pair(0,cityValues[0]));result=max(result,cityValues[0]);flag[0][cityValues[0]]=true;while(q.empty()==false){pair<int,int> tmpPair=q.front();result=max(result,tmpPair.second);q.pop();for(int i=0;i<n;i++){if((i!=tmpPair.first) && (roads[i][tmpPair.first]=='Y' || roads[tmpPair.first][i]=='Y') ){int value=tmpPair.second^cityValues[i];if(flag[i][value]==true)continue;pair<int,int> next=make_pair(i,value);flag[i][value]=true;q.push(next);}}//end for loop}//end while loopreturn result;}///end method maxProfit};

原文的分析非常好,直接搬过来。。。

The name of this problem may reminds you of the well known NP-hard problems: Traveling Salesman. However, don't let the name of it lies to you. This is just an easy task for you to enjoy.

The problem gives us an undirected graph with N vertices. Vertices i (0 <= i < N) has a values value[i]. A cost for a specific path is the xor-sum of all the value of vertices belong to it. If one vertex was visited k times in the paths, its value will be also used k times in the xor-sum. Your mission is finding the maximal cost-path which start from vertex 0.

Let's study the recursion program below, which is some solution that you may think of at the first attempt:

Try(u, profit) {res = max(profit, res);for all v adjacent to uTry(v, profit xor value[u]);}int main() {res = 0;Try(0, values(0);}

Try(u, p) tell us the maximal cost-path we can achieve if we start at vertices u with the initial cost p. The program firstly will update the result (res) with the current profit, which we can surely achieve. Then it just tries to go to any vertex adjacent to u and continue to do the similar process.

Unfortunately, this algorithm does not work. Some states (u, profit) will be visited infinite number of times. For example, if the graph contains just two vertices A and B, both have values 0. The state (A, 0) or (B, 0) will be visited many times and the function Try will not return the answer.

We can fix it by marking the visited state. Our program should be like this:

Try(u, profit) {if mark[u, profit] return;res = max(profit, res);mark[u, profit] = true;for all v adjacent to uTry(v, profit xor value[u]);}int main() {res = 0;for all (u, p) mark[u, p] = false;Try(0, values[0]);}

This time, it works. You may realize that it is similar to the DFS (depth first search). Since BFS can be used as a substitution for DFS, you can also use a queue and apply BFS for this problem.


原创粉丝点击