SRM 608 T1 && T2

T1:

题目大意:

有n个盒子,第i个盒子里的糖果数量为[Li,Ri],且所有盒子的糖果数量总和为C。现在要选出最少的盒子,使得这些盒子里的糖果数量总和不会小于X。


基本思路:

假设我们选择了盒子集合S。则里面糖果数量至少为    T=max(sigma(i 属于S)Li, C-sigma(i不属于S)Ri)。我们的目标是T>= X且|S|最小。所以可以把sigma(I 属于S)Li,以及C-sigma(i不属于S)Ri单独考虑。这只要排个序就可以了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cstdlib>
#include<ctime>
using namespace std;

int cmp(const int &a,const int &b){
	return a>b;
}

class MysticAndCandies{
public:
	int minBoxes(int C, int X, vector <int> low, vector <int> high){
		int n=high.size();
		sort(low.begin(),low.end(),cmp);
		sort(high.begin(),high.end());
		int ans1=n,ans2=n;
		for (int i=0,t=0; i<n; ++i){
			t+=low[i];
			if (t>=X) {
				ans1=i+1;
				break;
			}
		}
		for (int i=0,t=0; i<n; ++i){
			t+=high[i];
			if (C-t>=X){
				ans2=n-i-1;
			}
		}
		return min(ans1,ans2);
	}
};


T2:

题目大意:

给定一张有向图,没有自环和重边。F(L)代表长度为L的路径总数,求最小的K使得当L趋近于无穷时,F(L)与L^K同阶。无解输出-1。

基本思路:

如果图内没有环,则K一定为0。如果图内有一个强联通分量,且不是个简单环,则方案一定是指数级别的,所以无解。剩下的情况就是一些简单环之间通过边相连,如果把简单环当作点,把环之间的可达关系当作边,则就相当于是一张拓扑图。如果一条路径经过了C个简单环,则在分配在每个环上饶的圈数的方案和L^(C-1)同阶。由于我们只需要考虑同阶,所以简单环构成的拓扑图上的最长路C-1就是所求的K。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

bool f[55][55];
int parent[55], size_n[55],size_m[55] ;

int find(int x) {
    if (parent[x] != x) parent[x] = find(parent[x]);
    return parent[x];
}

int dp[55];
int n;

int dfs(int x) {
    if (dp[x]) return dp[x];
    int &ans = dp[x];
    ans = 0;
    for (int j = 0; j < n; ++j)
	if (j != x && find(j) == j &&
	    f[j][x] && size_n[j] > 1) ans = max(ans, dfs(j));
    return ans = ans + 1;
}

class BigO {
public:
    int minK(vector <string> graph) {
	n = graph.size();
	for (int i = 0; i < n; ++i)
	    for (int j = 0; j < n; ++j)
		f[i][j] = (graph[i][j] == 'Y');
	for (int i = 0; i < n; ++i)
	    graph[i][i] = 1;
	for (int k = 0; k < n; ++k)
	    for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
		    f[i][j] |= f[i][k] & f[k][j];
	for (int i = 0; i < n; ++i)
	    parent[i] = i;
	for (int i = 0; i < n; ++i)
	    for (int j = 0; j < n; ++j)
		if (f[i][j] && f[j][i])
		    parent[find(i)] = find(j);
	for (int i = 0; i < n; ++i) 
	    for (int j = 0; j < n; ++j)
		if (graph[i][j] == 'Y' && find(i) == find(j))
		    ++size_m[find(i)];
	for (int i = 0; i < n; ++i)
	    ++size_n[find(i)];
	for (int i = 0; i < n; ++i)
	    if (size_m[find(i)] != size_n[find(i)] && size_n[find(i)] != 1) {
	    	return -1;
	    }
	memset(dp, 0, sizeof(dp));
	for (int i = 0; i < n; ++i)
	    if (find(i) == i && size_n[i] > 1)
		dfs(i);
	int ans = 1;
	for (int i = 0; i < n; ++i)
	    ans = max(ans, dp[i]);
	return ans - 1;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值