贪心算法实验总结

贪心算法实验总结

一、题目1描述

4-1 程序存储问题 (40 分)

设有n 个程序{1,2,…, n }要存放在长度为L的磁带上。程序i存放在磁带上的长度是 li,1≤i≤n。 程序存储问题要求确定这n 个程序在磁带上的一个存储方案, 使得能够在磁带上存储尽可能多的程序。 对于给定的n个程序存放在磁带上的长度,计算磁带上最多可以存储的程序数。

 

输入格式:

第一行是2 个正整数,分别表示文件个数n和磁带的长度L。接下来的1行中,有n个正整数,表示程序存放在磁带上的长度。

 

输出格式:

输出最多可以存储的程序数。

 

输入样例:

在这里给出一组输入。例如:

 

6 50

2 3 13 8 80 20

结尾无空行

输出样例:

在这里给出相应的输出。例如:

 

5

结尾无空行

 

二、贪心策略:最小程序优先存入磁盘

 

三、具体实现:把所有的程序按长度有小到大排序,在将程序放入磁盘前先判断程序和磁盘的长度大小来判断程序能否放入程序,若能放入,磁盘存储长度减去放进的程序的长度,计数变量加一,最后输出计数变量

 

四、代码实现:

#include <iostream>

#include <algorithm>

using namespace std;

int n,L;

int a[1000];

 

 

int main(int argc, char** argv) {

   cin>>n>>L;

   for(int i=1;i<=n;i++){

      cin>>a[i];

   }

   sort(a,a+n);

   int count =0;

 

   for(int i=1;i<=n;i++){

      if(a[i]<=L){

          count++;

            L -= a[i];

      }

   }

   cout<<count;

   return 0;

}

 

一、题目2描述

   4-2 删数问题 (30 分)

给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最小的删数方案。如果数字最前面有0不输出。

 

输入格式:

第 1 行是1 个正整数 a。第 2 行是正整数k。

 

输出格式:

输出最小数。

 

输入样例:

在这里给出一组输入。例如:

 

178543

4

结尾无空行

5001

1

结尾无空行

123456

2

结尾无空行

109

1

结尾无

二、贪心策略:把数字以字符形式输入,再转换成数字比较,从左边开始比较,若左边的数字比右边的大,则删除该数,若该数为最后一位,则删除该数本身,若比较完之后,还没有删除要求的个数,而此时数组已经按递增排列,所以从最后一位开始删掉剩余的个数即可。

三、代码实现:

import java.util.Scanner;

 

public class Main {

 

    private static String a;

    private static int k;

    private static int m;

    private static StringBuffer str;

 

    public static void main(String[] args){

        Scanner input = new Scanner(System.in);

 

        while (true){

            a = input.next();

            k = input.nextInt();

 

            m = a.length();

            str = new StringBuffer(a);

 

            delk();

 

            System.out.println(str);

        }

    }

 

    //最近下降点优先

    private static void delk(){

        int i;

        if(k >= m)

            return;

        while (k > 0){

            for(i=0; (i<str.length()-1) && (str.charAt(i)<=str.charAt(i+1)); i++);//注意这里是提取str中的递增元素,将大的数字跳出循环然后删除

            str.deleteCharAt(i);

            k--;

        }

        while(str.length()>1 && str.charAt(0)=='0')

            str.deleteCharAt(0);

    }

}

 

一、题目3描述

   PTA 程序设计类实验辅助教学平台

算法第4章实践

剩余时间:1天

4-3 最优合并问题 (30 分)

题目来源:王晓东《算法设计与分析》

 

给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。 假设所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。试设 计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。

 

输入格式:

第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。

 

输出格式:

输出最多比较次数和最少比较次数。

 

输入样例:

在这里给出一组输入。例如:

 

4

5 12 11 2

结尾无空行

输出样例:

在这里给出相应的输出。例如:

 

78 52

结尾无空行

 

二、贪心策略

       最少比较次数:最短序列优先比较,将待合并序列按从短到长排列,每次从中选取最短的两个序列计算比较次数,每次比较之后,要把被比较元素的下一个元素加上其前面的元素,并且要重新对待排序序列进行排序,因为元素经过改变后可能会使得原来的序列的递增规律被破坏

  最多比较次数:与最少相反,最长优先,其余类比最少比较次数

 

三、代码实现

      #include <iostream>

#include <algorithm>

using namespace std;

int n;

int a[1000];

int b[1000];

 

 

bool comp(int a ,int b){

      return a>b;

}

 

int main(int argc, char** argv) {

      cin>>n;

      for(int i=1;i<=n;i++){

              cin>>a[i];

              b[i]=a[i];

      }

     

      int max=0;

      int min=0;

      for(int i=1;i<n;i++){

              sort(a+i,a+n+1);

              min+=a[i]+a[i+1]-1;

              a[i+1]+=a[i];

      }

      for(int i=1;i<n;i++){

              sort(b+i,b+n+1,comp);

              max+=b[i]+b[i+1]-1;

              b[i+1]+=b[i];

      }

      cout<<max<<" "<<min;

      return 0;

}

 

实验心得:对于贪心算法相关问题首先需要找出解决问题的贪心策略,然后再具体实现

posted @ 2021-11-15 16:59  暖云  阅读(662)  评论(0编辑  收藏  举报