B鞋店
时间限制 : - MS 空间限制 : 265526 KB
评测说明 : 1s
问题描述
何老板经营的鞋店有n双鞋。每双鞋都有一定价格和尺码,对于第i双鞋,Ci表示它的价格,Si表示它的尺码。每双鞋的尺码都不相同。
店里来了m个客户,每个客户都想买一双鞋,其中第i个客户有Di块钱,他的脚的尺码是Li。每个客户都愿意买尺码跟他脚相同或者大一码的鞋子。也就是对于j号鞋子,若满足(Cj<=Di)&&(Li==Sj||Li==Sj-1),i号客户就愿意买j号鞋。
贪婪的何老板希望卖出去的鞋子的总价尽可能高,请你帮他算算,他最多能卖出多少钱?
注意:一个顾客最多买一双鞋,一双鞋最多卖给一个顾客
输入格式
第一行,一个整数n
接下来n行,每行两个整数Ci和Si,表示一双鞋子的价格和尺码
接下来一行,一个整数m
接下来m行,每行两个整数Di和Li,表示一个客户的钱和他的脚的尺码
输出格式
一行,一个整数,表示能卖出去的最大总额。
样例输入 1
3
10 1
30 2
20 3
2
20 1
20 2
样例输出 1
30
样例输入 2
3
10 4
20 5
30 6
2
70 4
50 5
样例输出 2
50
提示
对于30%的数据1<=n,m<=100
对于100%的数据:
**1<=n<=5000
1<=m<=10000**
1<=Ci,Si,Di,Li<=1000000000
这道题目考试的时候只得了七十分
仔细反思了一下,方法做法都是对的
错的原因就是
做了各种花里胡哨的优化
没错这道题目数据很大
但是你除了输入优化之外
什么都不要优化!!
有一句说一句,这个顾客好傻啊,店主给啥他就买啥…
题解
这道题目其实不难想
由于一双鞋只能对应一个人,所以就是求最大匹配嘛
但这道题目还有一个条件,就是要求收入最高
那么换言之就是求边权最大的最大匹配嘛
但是最大匹配是没有边权的,怎么办呢
题目给了一个很重要的信息,就是老板很贪心
所以就贪心嘛
先按照价格给鞋子排序
然后从最贵的鞋开始匹配
只要匹配上了,就把这双鞋给卖出去
最后得到的和就是结果
解惑
①是否存在不是最大匹配却是最大解的情况呢?
不存在的
我们假设已经跑出了一个最大匹配,并且这个匹配当中不包含可以卖出的最贵的鞋子
那么可以买最贵的鞋子的那个人一定在最大匹配当中
我们就把那个人的鞋子换成了最贵的鞋子
假如可以买最贵的鞋子的那个人不在这个匹配当中
那么这个匹配一定不是最大匹配
因为你还可以加一条边(这个人买最贵的鞋子)
②数组开多大呢
由于最多有5000双鞋,10000个人
那么最大的情况就是10000个人每个人都能匹配到每一双鞋
就是最多的边数=5000*10000
至于鞋子什么的
就是5000双
人就不用存进数组里头了
③如何对鞋子进行排序呢(毕竟鞋子含有鞋码和钱两个参数)
结构体排序
详情见代码
附上代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
inline int input()
{
char c=getchar();int o;
while(c>57||c<48)c=getchar();
for(o=0;c>47&&c<58;c=getchar())o=(o<<1)+(o<<3)+c-48;
return o;
}
struct buy{int mon,size;}shoe[12345];//结构体
bool comp(buy a,buy b){return a.mon>b.mon;}//结构体排序函数
long long res=0;//结果可能超int,所以用long long
int n,m;
int went[12345],fath[12345];
int all=0,star[56780000],ent[56780000],nxt[56780000];
bool find(int s,int t)//最大匹配,用第二个变量t避免大规模高次数的memset
{
int bian,e;
for(bian=star[s],e=ent[bian];bian;bian=nxt[bian],e=ent[bian])
if(went[e]!=t)
{
went[e]=t;
if(!fath[e]||find(fath[e],t))
{
fath[e]=s;
return 1;
}
}
return 0;
}
void add(int s,int e)
{
nxt[++all]=star[s];
star[s]=all;
ent[all]=e;
}
int main()
{
int mon,size;
n=input();
for(int i=1;i<=n;i++)shoe[i].mon=input(),shoe[i].size=input();
sort(shoe+1,shoe+n+1,comp);
m=input();
for(int a=1;a<=m;a++)
{
mon=input();size=input();
for(int i=1;i<=n;i++)
if((shoe[i].size==size||shoe[i].size==size+1)&&shoe[i].mon<=mon)
add(i,a);
}
for(int i=1;i<=n;i++)if(find(i,i))res+=shoe[i].mon;//由于已经排过序,所以此处是从贵的鞋开始匹配
printf("%lld",res);
}