题目
题解思路
必然是贪心,但是贪心策略想不出,还是太弱了,这题朴素贪心居然也能过,数据太弱了。
从大佬的博客 看到的贪心策略。
将商品的价格从大到小排序,每次让商品从过期时间往前选择,这样对其他商品造成的影响就是最小的。
用朴素的方法的话,时间复杂度为 N平方 数据为1e4 应该要到极限才对。
我们可以用并查集优化, 将空闲的时间连接起来,因为进行了路径压缩,所以能节省复杂度。
将时间数组初始化为 -1 。
每次使用时,对时间进行find,返回离节点最近的空闲时间,使用后将时间指向时间-1的节点。
int find2( int x )
{
if ( -1 != pe[x] )
{
pe[x] = find2(pe[x]);
return pe[x]; //用于压缩路径
}
return x; //这里返回节点
}
这个find函数有些难理解,建议手模下。
AC代码
并查集优化
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct sp
{
int w,t;
bool operator < (const sp &other) const
{
return w > other.w;
}
}a[10010];
int pe[10010];
int find2( int x )
{
if ( -1 != pe[x] )
{
pe[x] = find2(pe[x]);
return pe[x];
}
return x;
}
int main ()
{
int n;
while(~scanf("%d",&n))
{
int ans = 0;
memset(pe,-1,sizeof(pe));
for (int i = 1 ; i <= n ; i++ )
{
int j,k;
scanf("%d%d",&j,&k);
a[i].w = j;
a[i].t = k;
}
sort(a+1,a+1+n);
for (int i = 1 ;i <= n ; i++ )
{
int time = find2(a[i].t);
if ( time > 0 )
{
ans += a[i].w;
pe[time] = time - 1;
}
}
cout<<ans<<"\n";
}
return 0;
}
朴素贪心
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct sp
{
int w,t;
bool operator < (const sp &other) const
{
return w > other.w;
}
}a[10010];
bool slo[10010];
int main ()
{
int n;
while(~scanf("%d",&n))
{
int ans = 0;
memset(slo,0,sizeof(slo));
for (int i = 1 ; i <= n ; i++ )
{
int j,k;
scanf("%d%d",&j,&k);
a[i].w = j;
a[i].t = k;
}
sort(a+1,a+1+n);
for (int i = 1 ;i <= n ; i++ )
{
for (int k = a[i].t ; k > 0 ; k-- )
{
if (slo[k] == 0 )
{
slo[k] = 1;
ans += a[i].w;
break;
}
}
}
cout<<ans<<"\n";
}
return 0;
}