(CodeForces) Round #387 (Div. 2) D,Winter Is Coming E,Comments

本文介绍了一道关于冬季轮胎使用的贪心算法题目,旨在找到最小化的轮胎更换次数,确保主人公能够安全度过冬季。通过将温度序列划分为正负数段并采用特定的贪心策略来解决问题。

D. Winter Is Coming(贪心)

题目大意:有一条冬季轮胎,可以在零下的温度使用,而且寿命为k天。夏季轮胎只能在零上的温度使用,但寿命不限。然后有n天,并且给你n天的温度。求最少的换胎次数,使得主人公可以安全度过冬季。

解题思路:一开始想的也是贪心,就是一开始能省则省,如果最后一段可以不换,那就不换。很快就把自己驳倒了,这是个傻逼策略无疑,因为中间有些夹在两个负数段中的正数段可能个数很少,这时候不换胎,损耗的代价可能很少。其实想到这我们就可以得出正确的贪心策略了(可是做的时候傻逼了,各种傻逼)。我们将给的数列直接划分正数段和负数段,这肯定是间隔出现的,第一段正数段可以不考虑,而最后一段正数段放在最后考虑(如果有的话),如果我们一开始用最笨的方法,遇到负数段就换胎,结束了就换回来,那原始次数ans=2*nanum,我们从小到大的去考虑哪些正数段(按个数排序),看看现在的寿命可不可以将这个正数合并到负数段,可以那就ans-=2,这样最后如果k还有寿命,我们再去考虑最后那一段换不换回夏季胎。

我的代码丑陋,但是思路是这样的,我觉得挺清晰的。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=2e5+7;
int n,k,a[maxn],num[maxn],cnt=0;
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i)   scanf("%d",a+i);
    int na=0,nanum=0;
    int i=1;
    while(a[i]>=0) ++i;
    if(i>n){
        cout<<0<<endl;
        return 0;
    }
    for(;i<=n;){
        if(a[i]<0){
            na++;
            while(a[++i]<0 && i<=n) na++;
            nanum++;
        }
        else{
            int tp=1;
            while(a[++i]>=0 && i<=n) tp++;
            num[++cnt]=tp;
        }
    }
    if(na>k)    cout<<-1<<endl; //负数天>k,无疑不行
    else{
        k-=na;
        int ans=2*nanum;
        if(a[n]>=0){
            sort(num+1,num+cnt);
            for(int i=1;i<=cnt-1;++i){
                if(k>=num[i])   k-=num[i],ans-=2;
                else break;
            }
            if(k && k>=num[cnt])    ans--;
            cout<<ans<<endl;
        }
        else{
            sort(num+1,num+cnt+1);
            for(int i=1;i<=cnt;++i){
                if(k>=num[i])   k-=num[i],ans-=2;
                else break;
            }
            if(k>=0)   ans--;
            cout<<ans<<endl;
        }
    }
    return 0;
}

E. Comments(搜索)

题目大意:大概就是给你图,让你把不同深度的统计输出即可。

解题思路:无疑是搜索,但是他这个读入,自己写可能会比较繁琐的,但是如果用stringstream切割字符串那就会轻松很多了。string转int再用atoi那就没什么工作量了。string与int转换

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define fi first
#define se second
#define ms(_data,v) memset(_data,v,sizeof(_data))
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int maxn=1e6+5;
vector<string> dep[maxn];
int mx=1,tt;
string s,tp;
void solve(int step,int num,stringstream &ns){
	mx=max(step,mx);
	while((num--) && ns>>s>>tp){
		dep[step].pb(s);
		tt=atoi(tp.c_str());
		if(tt){
			solve(step+1,tt,ns);
		}
	}
}
int main(){
	std::ios::sync_with_stdio(0);
	cin>>s;
	for(int i=0;i<(int)s.size();++i)	if(s[i]==',')	s[i]=' ';
	stringstream str(s);
	solve(1,inf,str);
	cout<<mx<<endl;
	for(int i=1;i<=mx;++i){
		for(int j=0;j<(int)dep[i].size();++j){
			cout<<dep[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值