【算法笔记】 关于简单贪心的详细解释

1.三值排序

贪心策略:统计1,2,3的个数

首先在根据统计的个数规定1,2,3的区间

首先,将1的区间内有3的个数时交换并统计

然后,再在1的区间内找2

最后,在2的区间内找3

奉上pascal代码:

program used_pascal;
var n:integer;
    i,j,t,ans:longint;
    a:array[-10..10000] of longint;
    b:array[-10..10000] of longint;
begin
    read(n);
	for i:=1 to n do
	    read(a[i]);
	for i:=1 to n do
	    inc(b[a[i]]);
	for i:=1 to b[1] do
    begin
        if a[i]=3 then 
        begin
            for j:=n downto b[1]+1 do
                if a[j]=1 then 
                begin
                    t:=a[i];
                    a[i]:=a[j];
                    a[j]:=t;
					inc(ans);
					break;
                end;
		end;
		if a[i]=2 then
    	begin
		    for j:=b[1]+1 to n do
			    if a[j]=1 then 
                begin
                    t:=a[i];
                    a[i]:=a[j];
                    a[j]:=t;
					inc(ans);
					break;
                end;
		end;
	end;
	for i:=b[1]+1 to b[1]+b[2] do
	    if a[i]=3 then 
            begin
                for j:=b[1]+b[2]+1 to n do
                    if a[j]=2 then 
                    begin
                        t:=a[i];
                        a[i]:=a[j];
                        a[j]:=t;
					    inc(ans);
					    break;
                    end;
		    end;
	write(ans);
end.

2.修理牛棚

首先,排序

其次,按间隔排序,由题意可知要-1

最后根据排序结果累加

最后减一减即可

其贪心策略要求木材尽量小,间隔尽量大,自然要通过排序来解决,也就形成了这道题目的贪心策略

非主流代码如下(暴露真名惹):

#include
using namespace std;
inline bool ZhouYibo_2023_cmp (int x,int y){return x>y;
}
int main()
{
	int h,s,c,k=0;
	int a[10000]={};
	cin>>h>>s>>c;
	for (int i=1;i<=c;i++)
	    cin>>a[i];
	sort(a+1,a+c+1);
	int b[10000]={};
	for (int i=1;i<c;i++)
	    b[i]=a[i+1]-a[i]-1;
	sort(b+1,b+c,ZhouYibo_2023_cmp);
	for (int i=1;i<=h-1;i++)
	    k+=b[i]; cout<<a[c]-a[1]+1-k;
}

3.游荡的奶牛

为了使线段后后面部分产生影响,按照右端点

又因为为了使尽量挑长度小的覆盖,所以相同右端点时起点靠右边的在前面

//贪心策略:按右端点排序,防止最右边产生影响 
#include
struct AC{
	int left,right;
}Line[100000]={};
inline bool cmp(AC x,AC y){return x.right<y.right;}
int n;
using namespace std;
int main()
{
	cin>>n;
	for (int i=1;i<=n;i++)
	   cin>>Line[i].left>>Line[i].right;
	sort(Line+1,Line+n+1,cmp);
	int now=1,ans=1;
	for (int i=1;i<=n;i+=1)
	{
		if (Line[now].right<=Line[i].left)
		    now=i,
		    ans++;
	} 
	cout<<ans;
	return 0;
}

4.游荡的奶牛

同样,只要变换一下判断条件,即if语句

原来是:判断这条线所放的地方有没有被放过

现在是:判断这条线所能放的每一个地方被放过的次数是否都

#include
struct AC{
	int left,right;
}Line[100000]={};
inline bool cmp(AC x,AC y){return x.right<y.right ||( (x.right==y.right&&x.left>=y.left) ); }
int n,k;
int num[100000]={};
int answer=0;
using namespace std;
int main()
{
	cin>>n>>k;
	for (int i=1;i<=n;i++)
	{
		int A,C,B;
		cin>>A>>C>>B>>C;
		Line[i].left=min(A,B);
		Line[i].right=max(A,B);
	}
	sort(Line+1,Line+n+1,cmp);
	for (int i=1;i<=n;i++)
	{
		int flag=0;
		for (int Check=Line[i].left;Check<=Line[i].right;Check++)
			if (num[Check]>=k) 
			{
				flag=1;
				break;
			}
		if (flag==1) continue;
		for (int Now=Line[i].left;Now<=Line[i].right;Now++)
		    num[Now]++;
		answer++;
	}
	cout<<n-answer;
	return 0;
}

5.删数问题

....未完待续


你可能感兴趣的:(【算法笔记】 关于简单贪心的详细解释)