A和E是签到题,就不写题解了。这里写一个C的贪心做法:
(要用到面向对象的思路)
首先预处理将所有的1连续段设置成一个类(结构体),这个结构体有连续段长度、中间的休息时间两个变量。很明显,对于给定的连续的‘1’,最终的最优工作方式是尽量平均的分配。例如,总共10天连续工作,若安排2天休息,那么一定是 3+(1)+3+(1)+2这样安排比较好。给定了以上两个变量的类,可以O(1)计算出最大连续时间、以及最优总消耗。
那么这道题就很简单了,开一个优先队列,每次“最大连续时间”的对象出队,给它添加一个新的休息时间即可。(最初所有连续段的休息时间都是0)
ac代码:
#include<bits/stdc++.h> using namespace std; struct node{ int len,kong; void judge(){ cout<<this->len<<" "<<this->kong<<endl; } node(int len,int kong){ this->len=len; this->kong=kong; } int getDx(){ return (len+1)/(kong+1)+((len+1)%(kong+1)!=0)-1; } int getValue(){ int ma=this->getDx(); int cnt=kong+ma*(kong+1)-len; return cnt*(ma-1)*ma/2+(kong+1-cnt)*(ma+1)*ma/2; } }; struct cmp{ bool operator()(node a,node b){ return a.getDx()<b.getDx(); } }; int main(){ // node tt(2,1); // cout<<tt.getDx()<<" "<<tt.getValue(); int n,i,j,k; cin>>n>>k; string s; cin>>s; vector<int>v; priority_queue<node,vector<node>,cmp>q; int cnt=0,sum=0,res=0; for(i=0;i<n;i++){ if(s[i]=='1'){ cnt++; } else{ node temp(cnt,0); q.push(temp); sum+=temp.getValue(); res+=cnt; cnt=0; } } if(cnt){ node temp(cnt,0); q.push(temp); res+=cnt; sum+=temp.getValue(); } // cout<<sum<<" "<<k<<" "<<res<<endl; while(sum>k){ node temp=q.top(); //temp.judge(); q.pop(); sum-=temp.getValue(); node temp2(temp.len,temp.kong+1); sum+=temp2.getValue(); // cout<<sum<<endl; q.push(temp2); res--; } //cout<<sum<<" "<<k<<" "<<res<<endl; cout<<res; }