1. 程式人生 > >面試題:從給定的N個正數中選取若干個數之和最接近M

面試題:從給定的N個正數中選取若干個數之和最接近M

這道題跟撈魚問題一樣,都是剛進實驗室新生培訓那會兒做過的題目,不過這個是一師姐當時找工作的面試題。
如題,並輸出該子序列
測試用例:2,9,5,7,4,11,10
分別輸出最接近33、40、47、60的子序列
分析:N個數之和接近M,將M看做一個容量的揹包,這個題目就變成了典型的01揹包,M容量下求最優解並輸出最優方案,這在01揹包中都整理過,上程式碼:

#include <iostream>
using namespace std;

char state[11][101]; /* 設 N <= 10 M <= 100 記錄路徑 */
int dp[101];         /* 使用一維陣列01揹包 */
int value[11]; /* 本題可將費用與價值看做同一值 */ int i, j; void main() { int N, M; scanf("%d", &N); for(i = 0; i < N; ++i) { scanf("%d",&value[i]); } while(scanf("%d", &M) != EOF) { memset(dp,0,sizeof(dp)); /* 01揹包 */ for(i = 0; i < N; ++i) { for
(j = M; j >= value[i]; --j) { int tmp = dp[j-value[i]] + value[i]; if(tmp > dp[j]) { dp[j] = tmp; state[i][j] = 1; } } } printf("最接近值:%d\n",dp[M]); /* 輸出方案 */
i = N; j = M; while(i-- >= 0) { if(state[i][j] == 1) { printf("%d ",value[i]); j -= value[i]; } } printf("\n"); } }
#include <iostream>
#include <list>
using namespace std;

int value[11];
int i, j;
list<int> seq;

/* 尋找可能的序列 */
void find_seq(int sum, int index)
{
    if(sum <= 0 || index < 0)
        return;
    if(sum == value[index])
    {
        seq.reverse();
        printf("%d ", value[index]);
        for(list<int>::iterator iter = seq.begin(); iter != seq.end(); ++iter)
        {
            printf("%d ", *iter);
        }
        printf("\n");
        seq.reverse();
    }

    seq.push_back(value[index]); // 放入
    find_seq(sum-value[index],index-1);
    seq.pop_back();
    find_seq(sum,index-1);       // 不放入
}

void main()
{
    int N, M;
    scanf("%d", &N);
    for(i = 0; i < N; ++i)
    {
        scanf("%d",&value[i]);
    }
    scanf("%d", &M);
    printf("可能的序列:\n");

    find_seq(M,N-1);
}