Topcoder SRM593 MayTheBestPetWin

10 篇文章 0 订阅
1 篇文章 0 订阅

Problem Statement

 The pony Rainbow Dash wants to choose her pet. There are N animals who want to be her pet. Rainbow Dash numbered them 0 through N-1.

To help her make the decision, Rainbow Dash decided to organize a relay race for the animals. The race track is already known, and for each animal we know how fast it is. More precisely, you are given vector <int>sA andB with the following meaning: For each i, the animal number i will take betweenA[i] andB[i] seconds (inclusive) to complete the track.

For the race the animals will be divided into two competing teams. This is a relay race, so the team members of each team will all run the same track, one after another -- when the first team member finishes, the second one may start, and so on. Thus the total time in which a team completes the race is the sum of the times of all team members. Note that we can use the estimates given byA andB to estimate the total time for any team of animals.

Given two teams S and T, the value maxdiff(S,T) is defined as the largest possible difference in seconds between the time in which team S finishes the course and the time in which team T finishes the course.

Rainbow Dash now needs to assign each of the animals to one of the two competing teams. She wants to see a close competition, so she wants the teams to finish as close to each other as possible. Formally, she wants to divide all animals into teams S and T in a way that minimizes maxdiff(S,T). Return the smallest possible value of maxdiff(S,T).

Definition

 
Class:MayTheBestPetWin
Method:calc
Parameters:vector <int>, vector <int>
Returns:int
Method signature:int calc(vector <int> A, vector <int> B)
(be sure your method is public)
 
 

Notes

-The teams are not required to contain the same number of animals.

Constraints

-A will contain between 2 and 50 elements, inclusive.
-A and B will contain the same number of elements.
-Each element of A will be between 1 and 10,000, inclusive.
-Each element of B will be between 1 and 10,000, inclusive.
-For each i, B[i] will be greater than or equal to A[i].

Examples

0) 
 
{3,4,4,7}
{3,4,4,7}
Returns: 2
In this test case we know the exact time in which each of the animals completes the track. An optimal solution is to choose teams S={0,3} and T={1,2}. Then team S will certainly complete the track in 3+7 = 10 seconds, and team T in 4+4 = 8 seconds. Thus, maxdiff(S,T)=2.
1) 
 
{1,3,5,4,5}
{2,5,6,8,7}
Returns: 5
Here one of the optimal solutions is S={2,3} and T={0,1,4}. For these two teams we have maxdiff(S,T)=5. For example, it is possible that S will complete the track in 6+8 = 14 seconds, and T will complete it in 1+3+5 = 9 seconds. It is also possible that S will complete the track up to 5 seconds before T does.
2) 
 
{2907,949,1674,6092,8608,5186,2630,970,1050,2415,1923,2697,5571,6941,8065,4710,716,756,5185,1341,993,5092,248,1895,4223,1783,3844,3531,2431,1755,2837,4015}
{7296,6954,4407,9724,8645,8065,9323,8433,1352,9618,6487,7309,9297,8999,9960,5653,4721,7623,6017,7320,3513,6642,6359,3145,7233,5077,6457,3605,2911,4679,5381,6574}
Returns: 52873

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.     


比赛的时候完全想对了,可是还是做不出来。。。当时写成了一个背包。。。其实是个经典的集合元素和问题。很好的DP。

看了tourist的代码,大神就是大神(男神V5)。。。。学习之。。。。

题目可以转化成一维,只讨论所选集合T,结果只与(sum (a[i] +b[i]) i属于T)有关,是max(abs(sa - sumT), abs(sumT - sb));

一开始发现和为定值,想做一个不超过(sa + sb)/2的背包,但是卡在枚举递推关系上了,其实本质还是要求出集合元素和。tourist的代码就是很简练,以后就这么做这种集合元素和问题。。。

思想就是DP,如果暴力枚举会有许多重复,假设你有100个元素,暴力是2^100,但显然所有元素和都没有这么大,肯定有很多数是可以由多种集合得到,又重复问题,所以DP,用法f[1000005],表示i能不能被取到(表示成集合元素的和),一开始元素和为0,f[0] = 1, tot记录当前元素和,对于新加的一个元素,前面所有可以得到的i加上它都可以,所以有一个遍历过程,把所有f[i]求出以后,就是直接重头到尾,取最小值。详见代码(自己重写了一个):

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

int f[1000005], c[55];


class MayTheBestPetWin {
public:
	int calc(vector <int> A, vector <int> B) {
		int sa, sb, i, j, l = A.size();
		for (i = 0; i < l; ++i) sa += A[i], c[i] += A[i];
		for (i = 0; i < l; ++i) sb += B[i], c[i] += B[i];
		int tot = 0;
		for (i = 0, f[0] = 1; i < l; ++i){
			for (j = tot; j >= 0; --j) 
				if (f[j]) f[j + c[i]] = 1;
			tot += c[i];
		}
		int ans = (int ) 1e9;
		for (i = 0; i <= tot; ++i){
			if (f[i]){
				ans = min(ans, max(abs(sa - i), abs(sb - i)));
			}
		}
		return ans;
	}
};
其实tourist的代码还有一点更巧妙。。。他不需要sb这个值来求最小值,而是每步取i, tot - i的最大值,然后取当前最小,一开始想不通,画图就可以明白了。

数轴上有两个点sa, sb, 一个点sT在他们之间,求min(max(sT - sa, sb - sT)), 其实就是离中点最近的点,如果sT在中的左边,较大值应该是和sb想减,但是我们做个对称就可以变成与sa相减,而对称的坐标就是tot - i.

再次膜拜男神。。。。。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值