1. 程式人生 > >高效演算法設計_貪心法(最優裝載問題,部分揹包問題,乘船問題)

高效演算法設計_貪心法(最優裝載問題,部分揹包問題,乘船問題)

最優裝載問題

題目:有一批集裝箱要裝上一艘載重量為c的輪船。其中集裝箱i的重量為Wi。

輸入:

100 6
100 20 25 25 20 20

輸出:

20 20 20 25 25 100
1 1 1 1 0 0

思路:最優裝載問題要求確定在裝載體積不受限制的情況下,將盡可能多的集裝箱裝上輪船。

#include<stdio.h>
#include<algorithm>
using namespace std;
// 貪心選擇裝載
void loading(int box[],int res[],int w,int n){
    res[0]=1;
    w-=box[0];
    for
(int i=1;i<n;i++) { if(w-box[i]>=0){ w-=box[i]; res[i]=1; } } } int main() { int w,n,i; int a[10010],ans[10010]; scanf("%d%d",&w,&n); for(i=0;i<n;i++) scanf("%d",&a[i]); sort(a,a+n); for (i=0;i<n;i++) printf("%d "
,a[i]); printf("\n"); loading(a,ans,w,n); for (i=0;i<n;i++) printf("%d ",ans[i]); printf("\n"); return 0; }

* *

題目:給定n種物品和一個揹包。物品i的重量是Wi,其價值為Vi,揹包的容量為C。

應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大?

注:在選擇裝入揹包的物品時,對每種物品i只有2種選擇,即裝入揹包或不裝入揹包。不能將物品i裝入揹包多次,也不能只裝入部分的物品i。

輸入:

4 50
10 60
30 120
20 100
40 120

輸出:

0 10 6 1.000000
2 20 5 1.000000
1 30 4 0.666667
3 40 3 0.000000

思路:選擇價值大的線裝入,知道裝不進入,將最後一個按照比例裝入

#include <stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node{
    int id;
    int w;//重量
    int v;//價值
    int s;//價值除以重量*100
    double flag;//標記
}Node;
Node p[1000];//結構體陣列,用來儲存每個物體
int ans[1000];//每個物體拿走的比例
void loading(int n,int c){
    int i;
    p[0].flag=1;
    c-=p[0].w;
    for(i=1;i<n;i++){
        if((c-p[i].w)>0){
            c-=p[i].w;
            p[i].flag=1;
        }
        else break;
    }
    if(c==0) return;
    else{
        p[i].flag=(double)c/p[i].w;
        return ;
    }
}

int main() {
    int n,c,i;//c為總重量
    scanf("%d%d",&n,&c);
    int k=0;
    for(i=0;i<n;i++){
        scanf("%d %d",&p[i].w,&p[i].v);
        p[i].s=p[i].v/p[i].w;
        p[i].id=k++;
    }
    for(i=0;i<n;i++){
        for(int j=i;j<n;j++){
            if(p[i].s<p[j].s){
                Node t=p[i];
                p[i]=p[j];
                p[j]=t;
            }
        }
    }
    loading(n,c);
    for(i=0;i<n;i++) printf("%d %d %d %lf\n",p[i].id,p[i].w,p[i].s,p[i].flag);
    return 0;
}

乘船問題

題目:有n個人,第i個人重量為Wi。每艘船的最大載重量均為C,且最多隻能乘兩個人。用最少的船裝載所有人。

輸入:

7
150
40 50 90 105 110 120 130

7
140
40 50 90 105 110 120 130

7
130
70 80 90 100 110 120 130

輸出:

6
40 6 50 6 90 5 105 4 110 3 120 2 130 1
6
40 6 50 6 90 5 105 4 110 3 120 2 130 1
Wrong!
#include <stdio.h>
int a[10010],ans[10010],vis[10010];
int count=1;
int loading (int n,int m){
    int i,j;
    if(m<=a[n-1]) return -1;
    for(i=0;i<n;i++){
        for(j=n-1;j>i;j--){
            if(vis[j]==0 && (a[i]+a[j])<=m){
                ans[i]=ans[j]=count++;//一起搭船
//              printf("%d %d\n",a[i],a[j]);
                vis[i]=vis[j]=1;
            }
            else if(vis[j]==0 && a[i]+a[j]>m){
                ans[j]=count++;//獨自乘船
//              printf("%d %d\n",a[i],a[j]);
                vis[j]=1;
            }
        }
    }
    printf("%d\n",count-1);
    return 1;
}
int main() {
    int n,m,i,j;
    while(scanf("%d %d",&n,&m)!=EOF){
        for(i=0;i<n;i++) scanf("%d",&a[i]);
        //冒泡
        for(int i=0;i<n;i++){
            for(j=i;j<n;j++){
                if(a[i]>a[j]){
                    int t=a[i];
                    a[i]=a[j];
                    a[j]=t;
                }
            }
        }
    //  for(int i=0;i<n;i++) printf("%d %d ",a[i],ans[i]);
    //  printf("\n");
        int k=loading (n,m);
        if(k<0) printf("Wrong!");
        else{
            for(i=0;i<n;i++){
            printf("%d %d ",a[i],ans[i]);}
        }
        printf("\n");
    }
    return 0;
}