版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37220238/article/details/80013402
描述
输入共n+1行
第1行:收到短信数n
后n行:每行分别两个数,最后期限ti和过期滞纳金mi,用空格隔开输出最少的滞纳金总和样例输入
近些年来,生活水平越来越好,私家车也成了很多家庭必备之物。但某些司机总是不守交规,罚单也是接踵而至。
有一位不遵守交规的司机,在同一天收到了n条违章罚单短信(1≤n≤100),每条罚单短信中有两个内容,一:交罚款的最后剩余时间ti;二:过期未交的滞纳金mi(1≤ti,mi≤1000),假设不管过期多少天,滞纳金数量不会改变,而且,这位司机很忙,每天最多只能处理一张罚单,那么,这位司机应该按怎样的处理违章短信的顺序,才能使滞纳金总和最少?
第1行:收到短信数n
后n行:每行分别两个数,最后期限ti和过期滞纳金mi,用空格隔开输出最少的滞纳金总和样例输入
4 1 50 1 100 2 60 3 60样例输出
50提示
贪心(调度问题)
解题思路
首先我们能够想到按照滞纳金的从大到小进行排序,但是真的是按照时间顺序处理这些从大到小的滞纳金吗?其实不是的,我们最优贪心思想应该是按照滞纳金的按照滞纳金的从大到小进行排序,越大的滞纳金能够拖到最后一天处理就最后一天处理;如果最后一天已经处理过以其他的滞纳金,则就从这一天倒着往前开始找,看看那一天没有处理过滞纳金,就在这一天处理该滞纳金;如果没有找到,则说明一定要缴纳此滞纳金。
参考程序贪心(调度问题)
#include<iostream>
#include<algorithm>
using namespace std;
struct message
{
int time,money;//最后剩余时间;滞纳金
}s[105];
int cmp(message a,message b)
{
return a.money>b.money;//按照滞纳金从大到小排列
}
int n,i,j,flag[105],flag1,tot=0;//flag表示第i天是否交了滞纳金
int main()
{
cin>>n;
for(i=1;i<=n;i++)
cin>>s[i].time>>s[i].money;
sort(s+1,s+1+n,cmp);
for(i=1;i<=n;i++)
{
flag1=0;
if(!flag[s[i].time])//如果到了该滞纳金的最后一天剩余时间没有处理过其他的滞纳金
{
flag[s[i].time]=1;//这一天处理这个滞纳金
continue;
}
else//如果到了该滞纳金的最后一天剩余时间已经处理过其他的滞纳金
for(j=s[i].time-1;j>=1;j--)//从这一天往前遍历,如果有空闲的天,则处理此滞纳金,flag置为1
{
if(!flag[j])
{
flag[j]=1;
flag1=1;
break;
}
}
if(!flag1)//如果在之前没有找到空闲天,则肯定要缴纳此滞纳金
tot+=s[i].money;
}
cout<<tot;
return 0;
}