가방 문제 시리즈 상세 설명
질문
N 개의 아 이 템 과 V 용량 의 가방 이 있 습 니 다.제 i 아 이 템 (아 이 템 당 1 개) 의 비용 은 c [i] 이 고 가 치 는 w [i] 입 니 다.어떤 물건 을 가방 에 넣 으 면 가 치 를 총화 할 수 있 는 지 알 아 보 세 요.가방 에 넣 을 아 이 템 을 선택 할 때 각 아 이 템 i 는 가방 에 넣 거나 가방 에 넣 지 않 는 두 가지 선택 만 있 습 니 다.아 이 템 i 를 가방 에 여러 번 넣 을 수 없고 일부 아 이 템 만 넣 을 수 없습니다.따라서 이 문 제 를 0 - 1 가방 문제 라 고 한다.
(1) 귀속 구 해
알고리즘 은 다음 과 같 습 니 다.
#include "iostream"
#define CAPACITY 10
#define GOODSNUM 6
using namespace std;
int nVol[GOODSNUM];
int nValue[GOODSNUM];
int knapsack(int itemIndex,int vol);
void main()
{
int i=0,j=0;
while(i<GOODSNUM)
{
cout<<"input the "<<i+1<<"th item(volume and value):";
cin>>nVol[i]>>nValue[i];
i++;
}
cout<<"The max value is: "<<knapsack(GOODSNUM,CAPACITY)<<endl;
}
int knapsack(int itemIndex,int vol)
{
if (itemIndex==0||vol==0)
{
return 0;
}
else if (vol>=nVol[itemIndex] && knapsack(itemIndex-1,vol)<knapsack(itemIndex-1,vol-nVol[itemIndex])+nValue[itemIndex])
{
return knapsack(itemIndex-1,vol-nVol[itemIndex])+nValue[itemIndex];
}
else
return knapsack(itemIndex-1,vol);
}
분석: 귀속 구 해, 구 해 과정 중의 대부분 변 수 는 중복 구 해 과정 이 존재 하고 알고리즘 의 효율 이 비교적 낮 으 며 개선 이 필요 하 다.그럼 어떻게 개선 할 까요?가장 효과 적 인 것 은 매번 계 산 된 결 과 를 배열 로 저장 하고 중복 계산 을 하지 않 아 도 되 기 때문에 2 차원 배열 의 풀이 가 있다.
(2) 2 차원 배열 의 풀이
알고리즘 은 다음 과 같 습 니 다.
#include "iostream"
#define CAPACITY 10
#define GOODSNUM 6
using namespace std;
void main()
{
int i=1,j;
int v[GOODSNUM] = {10,12,40,40,40,15};
int c[GOODSNUM] = {1,2,3,5,2,1};
int fun[GOODSNUM+1][CAPACITY+1];
for (i=1;i<=GOODSNUM;i++)
{
fun[i][0] = 0;
}
for (i=1;i<=CAPACITY;i++)
{
fun[0][i] = 0;
}
for (i=1;i<=GOODSNUM;i++)
{
for (j=1;j<=CAPACITY;j++)
{
if (j<c[i-1])
{
fun[i][j] = fun[i-1][j];
}
else if (fun[i-1][j]<fun[i-1][j-c[i-1]] + v[i-1])
{
fun[i][j] = fun[i-1][j-c[i-1]] + v[i-1];
}
else
fun[i][j] = fun[i-1][j];
}
}
cout<<"The max value is: "<<fun[GOODSNUM][CAPACITY]<<endl;
}
분석: 2 차원 배열 의 구 해 방법 은 재 귀적 인 구 해 보다 훨씬 좋 지만 그 공간 복잡 도 는 여전히 비교적 높 고 계속 개선 할 여지 가 있 습 니까?1 차원 배열 이 가능 합 니까?답 은 긍정 적 이다.
(3) 1 차원 배열 의 풀이
알고리즘 분석:
#include "iostream"
#define CAPACITY 10
#define GOODSNUM 6
using namespace std;
void main()
{
int nVolume[GOODSNUM] = {1,2,3,5,2,1};
int nValue[GOODSNUM] = {10,12,40,40,40,15};
int selectTable[GOODSNUM][CAPACITY+1] = {0};
int nKnapsack[CAPACITY+1] = {0};//most important for the first compution below
int itemIndex,capIndex;
for (itemIndex=0;itemIndex<GOODSNUM;itemIndex++)
{
for (capIndex=CAPACITY;capIndex>=nVolume[itemIndex];capIndex--)//notice that capIndex>=nVolume[itemIndex],not capIndex>=0
{
if (nKnapsack[capIndex]<nKnapsack[capIndex-nVolume[itemIndex]]+nValue[itemIndex])
{
nKnapsack[capIndex] = nKnapsack[capIndex-nVolume[itemIndex]]+nValue[itemIndex];
selectTable[itemIndex][capIndex] = 1;
}
else
nKnapsack[capIndex] = nKnapsack[capIndex];
}
}
cout<<"The max value is: "<<nKnapsack[CAPACITY]<<endl;
cout<<"The selected items are: ";
for (itemIndex = GOODSNUM-1,capIndex = CAPACITY;itemIndex>=0;itemIndex--)
{
if (selectTable[itemIndex][capIndex])
{
cout<<itemIndex+1<<" ";
capIndex = capIndex - nVolume[itemIndex];
}
}
cout<<endl;
}
분석: 1 차원 배열 에서 공간 복잡 도 를 O (GOODSNUM * CAPACITY) 에서 O (CAPACITY) 로 낮 추고 코드 최적화 와 함께 아 이 템 선택 번호 도 제시 했다.
2. 완전 가방 문제
0 - 1 가방 문제 와 그 깊 은 의 미 를 깊이 이해 하고 1 차원 배열 이 가방 문 제 를 해결 하 는 것 을 진정 으로 이해 할 수 있다 면 다음 문 제 는 당신 에 게 상당히 쉬 울 것 입 니 다.
완전 가방 문제: N 가지 아 이 템 과 V 용량 의 가방 이 있 으 며, 모든 아 이 템 은 무한 개 사용 가능 합 니 다.제 i 종 물품 의 비용 은 c [i] 이 고 가 치 는 w [i] 입 니 다.어떤 물건 을 가방 에 넣 으 면 이 물건 들 의 비용 을 합 쳐 가방 용량 을 초과 하지 않 고 가치 가 가장 큰 지 알 아 보 세 요.
분석: 목 표 는 0 - 1 가방 문제 로 전환 하 는 것 이다.만약 에 비용 / 용량 이 nVolume [itemIndex] 인 물품 을 CAPACITY / nVolume [itemIndex] 와 같은 비용 과 가치 의 물품 으로 전환 하면 앞의 세 가지 0 - 1 가방 문제 로 직접 해답 을 구한다.이외에 또 다른 실행 가능 한 해답 방법 이 있 습 니까?0 - 1 가방 문제 의 상태 방정식 f [i] [v] = max {f [i - 1] [v], f [i - 1] [v - c [i]] + w [i]} 에 대해 완전한 가방 문 제 를 얻 을 수 있 는 상태 방정식 f [i] [v] = max {f [i - 1] [v - k * c [i]] + k * w [i] | 0 < = k * c [i] < = v} 을 약간 분석 할 수 있 기 때문에 다음 알고리즘 실현 과정 이 있 고 최종 적 으로 선택 한 물품 과 이 아 이 템 을 선택 하 는 수량 을 제시 했다.
구현 알고리즘:
#include "iostream"
#define CAPACITY 10
#define GOODSNUM 6
using namespace std;
void main()
{
int num,k,max;
int nVolume[GOODSNUM] = {1,4,3,5,5,3};
int nValue[GOODSNUM] = {2,8,40,60,10,3};
int selectTable[GOODSNUM][CAPACITY+1] = {0};
int nKnapsack[CAPACITY+1] = {0};//most important for the first compution below
int itemIndex,capIndex;
for (itemIndex=0;itemIndex<GOODSNUM;itemIndex++)
{
for (capIndex=CAPACITY;capIndex>=nVolume[itemIndex];capIndex--)//notice that capIndex>=nVolume[itemIndex],not capIndex>=0
{
num = 0;
max = nKnapsack[capIndex];
for (k=1;k<=CAPACITY/nVolume[itemIndex];k++)
{
if (capIndex>=k*nVolume[itemIndex] && max<nKnapsack[capIndex-k*nVolume[itemIndex]]+k*nValue[itemIndex])
{
max = nKnapsack[capIndex-k*nVolume[itemIndex]]+k*nValue[itemIndex];
num = k;
}
}
nKnapsack[capIndex] = max;
selectTable[itemIndex][capIndex] = num;
}
}
cout<<"The max value is: "<<nKnapsack[CAPACITY]<<endl;
cout<<"The selected items are: "<<endl;
for (itemIndex = GOODSNUM-1,capIndex = CAPACITY;itemIndex>=0;itemIndex--)
{
if (selectTable[itemIndex][capIndex])
{
cout<<itemIndex+1<<":"<<selectTable[itemIndex][capIndex]<<" ";
capIndex = capIndex - selectTable[itemIndex][capIndex]*nVolume[itemIndex];
}
}
cout<<endl;
}
3. 다 중 가방 문제
다 중 가방 문제: N 가지 아 이 템 과 V 용량 의 가방 이 있 습 니 다.제 i 종 아 이 템 은 최대 n [i] 개 를 사용 할 수 있 습 니 다. 모든 비용 은 c [i] 이 고 가 치 는 w [i] 입 니 다.어떤 물건 을 가방 에 넣 으 면 이 물건 들 의 비용 을 합 쳐 가방 용량 을 초과 하지 않 고 가치 가 가장 큰 지 알 아 보 세 요.
다 중 가방 문제 의 기본 적 인 해결 방식 은 완전 가방 문제 와 같 고 유일한 것 은 제어 파라미터 k 의 제한 이 다르다 는 것 이다.완전 가방 문 제 를 실현 하 는 것 만 있 으 면 됩 니 다.
제한 조건
4. 567913. 그러면 됩 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Codility Lesson3】FrogJmpA small frog wants to get to the other side of the road. The frog is currently located at position X and wants to get to...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.