3703: 昊昊的壮举之造福社会

3703: 昊昊的壮举之造福社会

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 12   Solved: 4
[ Submit][ Status][ Discuss]

Description

“A secret makes a woman woman.”——Vermouth
“图灵机”昊昊,修八尺有余,而形貌昳丽,∴闻名遐迩。(昊昊:你们天天黑我因为我长得太帅了“众女嫉余之蛾眉兮,谣诼谓余以善淫”,你们啊,naive!!)有关人士称,据内部可靠消息,昊昊受到了很多“知名人士”的青睐,曾经参观过昊昊的知名人士,比如轲老板&老(da)板(biao)娘(mei),董天师&潮,黄大大&土豆泥,还有各种黄学长等。
这天,昊昊默默在给自己带来无限仰慕buff的财神爷面前矗立,私语道:“我是不是该造福社会了呢?”Action speaks louder than words.于是昊昊决定迈出卖出自己的第一步。
“图灵机”要造福社会,必从素有“图灵机之乡”的大胡建开始。不是有句名言“图灵机要从娃娃抓起”?于是昊昊找来了胡建各路名校,如zpyz等,希望他们能够买下昊昊领导的n个图灵机们。由于图灵机也实行“n品中正制”,故每台图灵机的价格不一定相同,要想买下第i台图灵机需要花费W[i]CNY,而每所学校对这项造福社会的事业的重视程度也不同,第i所学校的可支配资金为mon[i]CNY。为了简化问题,不妨假设图灵机是不可以被拆卸的,因此一个图灵机只能造福一个学校,但是一个学校为了自己拥有更强大的实力可以拥有多个图灵机。
昊昊自然是希望能够有尽量多的图灵机实行光荣的造福社会的使命,但是他还要四处奔波推销自己,因此这个任务就交给你咯^_^(昊昊:替我挡着~)

Input

第一行一个N,接下来N行,每行一个MON[I]。
接下来一行是一个M,之后M行,每行一个数,W[I]。

Output

仅一个数,即最多能被买下的图灵机的个数。

Sample Input

2
20
10
4
8
7
10
9

Sample Output


HINT

数据规模与约定

样例说明:4台图灵机两所学校不能都买下,所以最多只能买下3台。其中一种方案:第一所学校买下前两台,第二所学校买下第三台。

对于100%的数据:  0<N<=10000,0<M<=400000,0<mon<=1500,0<wi<=128


Source

[ Submit][ Status][ Discuss]

先是按照1246的套路全下
在考虑一些单调性的优化
因为价格相同的餐厅很多,以及有相同钱的商人很多
所以对于价格相同的餐厅,承包的商人的初始金钱要单调非增
这样可以减少很多冗余枚举
但是,有几个数据恰好卡了苟蒻的程序。。GG
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E4 + 10;
const int maxm = maxn*40;
const int maxs = 1E6 + 10;

int n,m,tot,MaxMoney,Min,Max,c[maxn],
	Last[130],mon[maxn],w[maxm],sum[maxm],top,
	Now[maxs],Waste[maxs],I[maxs],Pos[maxs],Rest[maxs];
bool bo[maxn];

bool DFS(int pos,int waste)
{
	if (waste > Max) return 0;
	if (!pos) return 1;
	int Now = Last[w[pos]];
	for (int i = Now; i >= 1; i--) {
		if (mon[i] < w[pos]) continue;
		mon[i] -= w[pos];
		int Add = 0;
		if (mon[i] < Min) Add = mon[i];
		Last[w[pos]] = i;
		if (DFS(pos-1,waste + Add)) return 1;
		mon[i] += w[pos];
	}
	Last[w[pos]] = Now;
	return 0;
}



int getint()
{
	char ch = getchar();
	int ret = 0;
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9')
		ret = ret*10 + ch - '0',ch = getchar();
	return ret;
}

bool Judge(int now)
{
	if (sum[now] > tot || w[now] > c[n]) return 0;
	
	Max = tot - sum[now];
	for (int i = 1; i <= n; i++) mon[i] = c[i];
	for (int i = 1; i <= now; i++)
		Last[w[i]] = n;
		
	return DFS(now,0);
}

int main()
{
	#ifdef DMC
		//freopen("DMC.txt","r",stdin);
		freopen("input5.in","r",stdin);
	#endif
	
	cin >> n;
	for (int i = 1; i <= n; i++) 
		c[i] = getint(),tot += c[i];
	cin >> m;
	for (int i = 1; i <= m; i++)
		w[i] = getint();
	sort(w + 1,w + m + 1);
	for (int i = 1; i <= n; i++)
		if (c[i] < w[1]) 
			tot -= c[i],bo[i] = 1;
	int N = 0;
	for (int i = 1; i <= n; i++)
		if (!bo[i]) c[++N] = c[i];
	sort(c + 1,c + N + 1); n = N;
	for (int i = 1; i <= m; i++)
		sum[i] = sum[i-1] + w[i];
	
	int L = 0,R = m;
	int posi = 1;
	for (int i = 1; i <= m; i++) {
		while (posi <= n && w[i] > c[posi]) 
			++posi;
		if (c[posi] >= w[i]) ++L,++posi;
	}
			
	while (R - L > 1) {
		int mid = (L + R) >> 1;
		if (Judge(mid)) L = mid;
		else R = mid;
	}
	if (Judge(R)) cout << R;
	else cout << L;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值