동적 계획 초보 (01 가방, 완전 가방, 다 중 가방)

11423 단어 알고리즘
동태 계획 에 관 한 문 제 는 중점 이자 어 려 운 점 이다.처음에 어떻게 끼어 들 어야 할 지 몰 랐 던 저 는 선배 님 의 건의 와 관련 자료 의 도움 을 받 아 동태 기획 에 대한 학습 을 비교적 간단 한 가방 부터 시 작 했 습 니 다.
01 가방
  용적 이 c 인 가방 을 정 하고 n 개의 무게 가 wi 이 고 가치 가 vi 인 물 체 를 포장 하여 포장 할 수 있 는 물체 의 최대 가 치 를 구 합 니 다.예 를 들 어 n = 3, c = 30, W [] = {16, 15, 15}, v = {45, 25, 25} 일 때 담 을 수 있 는 것 은 뒤의 두 물체 이 고 최대 가 치 는 50 이다.주어진 세 물체 의 경우 마지막 가방 에 나타 날 수도 있 고 가방 에 나타 나 지 않 을 수도 있다.물체 가 마지막 가방 에 나타 나 는 지 여 부 를 0 과 1 의 변수 로 표시 할 수 있다.하나의 물 체 를 하나의 전체 로 보면 모든 물체 가 가방 에 나타 나 는 것 은 하나의 길이 가 n 이 고 0 과 1 로 구 성 된 꼬치 로 표시 할 수 있다.분명히 모두 00... 00 에서 11.11 의 2 ^ n 가지 상황 이 존재 한다.00... 00 에서 11. 11 까지 이 문자열 을 10 진수 의 2 진법 표시 로 본다 면 10 진수 가 0 에서 2 ^ n - 1 입 니 다.이러한 전환 을 통 해 0 에서 2 ^ n - 1 로 순환 하 는 변 수 를 이용 하여 모든 물체 가 가방 에 나타 나 는 형 태 를 나타 내 고 이 를 n 길이 의 바 이 너 리 로 전환 할 수 있 으 며 해당 하 는 비트 의 수치 (0 과 1) 는 해당 하 는 물체 가 가방 에 나타 나 는 지 여 부 를 나타 낸다.이 사상 을 바탕 으로 디자인 된 절 차 는 다음 과 같다.
#include   
#include   
#define n 3  
#define c 30  
int w[n]={16,15,15};  
int v[n]={45,25,25};  
int main()  
{  
    int num,temp;  
    int i;  
    int tempvalue, tempweight;  
    int maxvalue=0;  
   
    for(num=0;nummaxvalue)  
          maxvalue=tempvalue;  
}  
   
printf("%d
",maxvalue); return 0; }

 이 코드 를 보고 01 가방 이 무엇 인지 대체적으로 알 게 되 었 을 것 이 라 고 믿 습 니 다. 그러나 이런 방법 은 현실 상황 에서 실 용적 이지 않 습 니 다. 물체 의 개수 가 많 을 때 물체 의 모든 배치 상황 을 일일이 열거 하면 계 산 량 이 상당히 커 질 것 입 니 다. 여기 서 01 가방 이 무엇 인지 이해 하 게 만 들 기 때 문 입 니 다.
  그 다음 에 우 리 는 동태 계획 처리 01 가방 을 말한다. 동태 계획 에서 01 가방 은 한 층 한 층 가장 좋 은 과정 이다. 모든 물품 은 두 가지 상태 만 놓 을 수 있 기 때문에 그의 상태 전이 방정식 은: dp[i][v]=max{dp[i-1][v],dp[i-1][v-cc[i]]+ww[i]};
  상태 전이 방정식 을 어떻게 이해 해 야 합 니까? 그 중에서 dp [i] [v] 메모리 에 놓 인 값 은 가방 안의 물체 의 가 치 를 나타 내 고 dp [i] [v] 중의 i, v 는 각각 i 번 째 물체 와 가방 의 용량 이 v 임 을 나타 냅 니 다.그래서 방정식 은 간단 해 졌 다.둘 중 큰 경 우 를 선택한다.앞에서 말 했 듯 이 이 과정 은 층 층 이 가장 좋 은 것 이다. 즉, i 번 째 물 체 를 놓 을 때 i - 1 번 물체 가 가장 좋 은 상황 이기 때문에 i 번 째 물 체 를 놓 을 때 앞 i - 1 번 물체 의 기초 위 에서 놓 을 지 여 부 를 선택 하 는 것 이다.
  상태 전이 방정식 을 알 겠 습 니 다. 몇 가지 문 제 를 보 겠 습 니 다.
  HDU2602  http://acm.hdu.edu.cn/showproblem.php?pid=2602
  제목 의 대의: 몇 년 전, 테 디 의 고향 에 '뼈 수집가' 라 는 남자 가 있 었 습 니 다.이 남 자 는 여러 가지 뼈 를 수집 하 는 것 을 좋아 합 니 다. 예 를 들 어 개, 소, 그 도 무덤 에 갔습니다. 뼈 수집 자 는 큰 자루 V 가 있 습 니 다. 그의 수집 여행 에는 뼈 가 많 습 니 다. 분명 한 것 은 서로 다른 뼈 가 서로 다른 가치 와 부 피 를 가지 고 있 습 니 다. 지금 은 그의 여행 중의 모든 뼈의 가 치 를 제시 합 니 다. 뼈 수집 기 가 얻 을 수 있 는 총액 의 최대 치 를 계산 할 수 있 습 니까?
  이것 은 분명히 01 배낭 문제 이다. 
  AC 코드:
#include   
#include   
#include   
using namespace std;  
int dp[1100][1100];  
  
int main (){  
    int T;  
    scanf ("%d",&T);  
    while(T--){  
        int N,V;  
        int WW[1100];  
        int VV[1100];  
        scanf ("%d%d",&N,&V);  
        memset(dp,0,sizeof(dp));  
        for (int i=1;i<=N;i++){  
            scanf ("%d",&VV[i]);  
        }  
        for (int i=1;i<=N;i++){  
            scanf ("%d",&WW[i]);  
        }  
        //                                             
        for (int i=1;i<=N;i++){  
            for (int j=0;j<=V;j++){  
                if(WW[i]<=j){//               i               
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-WW[i]]+VV[i]);  
                }  
                else{//               i                  i-1           
                    dp[i][j]=dp[i-1][j];   
                }  
            }  
        }  
          
        //                
        /*for (int i=0;i<=N;i++){ 
            for (int j=0;j<=V;j++){ 
                printf ("%5d",dp[i][j]); 
            }  
            putchar('
'); } */ printf ("%d
",dp[N][V]); } return 0; }

 
  
HDU1203
   http://acm.hdu.edu.cn/showproblem.php?pid=1203
  여기에 약간의 수학 기 교 를 사용한다. 최소한 의 오 피 스 를 받 을 수 있 는 가장 큰 확률 을 구 하 는 것 도 오 피 스 를 구 해도 받 을 수 없 는 가장 작은 확률 이 라 고 할 수 있다. 
  AC 코드:
#include   
#include   
#include   
using namespace std;  
float dp[100010];  
int mm[100010];  
float ff[100010];  
  
int main (){  
    int n,m;  
    while (scanf ("%d%d",&n,&m)&&(n||m)){  
        for (int i=0;i=mm[i];j--){//                  
                dp[j]=min(dp[j],dp[j-mm[i]]*ff[i]);   
            }  
        }  
        printf ("%.1f%%
",(1-dp[n])*100); } return 0; }

  HDU1864  http://acm.hdu.edu.cn/showproblem.php?pid=1864
  심사 문제 가 매우 중요 하 다.  데이터 처 리 는 매우 중요 한 문제 에서 소수 자릿수 를 제시 하기 때문에 우 리 는 소 수 를 정수 로 바 꾸 고 01 가방 을 풀 수 있다. 
  AC 코드:
#include   
#include   
#include   
using namespace std;  
int dp[3000001];  
int cost[33];  
int num[3];   
int main (){  
    int N;  
    float Q;  
    int Q2;  
    while (scanf ("%f%d",&Q,&N)&&N){  
        Q2=(int)(Q*100);  
        int len=0;  
        memset(dp,0,sizeof(dp));   
        memset(cost,0,sizeof(cost));  
        while (N--){  
            int m;  
            scanf ("%d",&m);  
            float x;  
            memset(num,0,sizeof(num));  
            int flag=1;  
              
            while (m--){  
                char o;  
                scanf (" %c:%f",&o,&x);  
                //     A B C               600   
                if (o=='A'&&x<=600){  
                    num[0]+=(int)(x*100);  
                }   
                else if (o=='B'&&x<=600){  
                    num[1]+=(int)(x*100);  
                }  
                else if (o=='C'&&x<=600){  
                    num[2]+=(int)(x*100);  
                }  
                else {//                     
                    flag=0;  
                }     
            }  
            if (num[0]+num[1]+num[2]<=1000*100&&num[0]<=600*100&&num[1]<=600*100&&num[2]<=600*100&&flag){  
                cost[len++]=num[0]+num[1]+num[2];  
            }  
        }  
        for (int i=0;i=cost[i];j--){  
                dp[j]=max(dp[j],dp[j-cost[i]]+cost[i]);  
            }  
        }  
          
        printf ("%.2f
",dp[Q2]/100.0); } return 0; }

 HDU2955 http://acm.hdu.edu.cn/showproblem.php?pid=2955
  제목: 한 강도 가 몇 개의 은행 에 가서 훔 치 려 고 하 는데 그 는 돈 을 더 투자 하고 싶 을 뿐만 아니 라 잡 히 지 않 으 려 고 한다.각 은행 의 돈 수 와 잡 힐 확률, 그리고 강도 가 용인 할 수 있 는 최대 잡 힐 확률 을 알 고 있다.그 에 게 가장 많 게 는 얼 마 를 훔 칠 수 있 습 니까?
  얼핏 보면 01 가방 제목 인 데 안에 문제 가 있어 요. 가방 의 용량 은 소수 이다. 이 건 곤란 합 니 다.그럼 우 린 어 떡 하지?사실 01 가방 변형 문제 입 니 다. 우 리 는 빼 앗 은 총 돈 수 를 가방 의 용량 으로 할 수 있다. 그리고 안 잡 힐 확률 을 구하 세 요. 맞아요. 안 잡 힐 확률 이에 요. 구 한 후에 다시 한 번 배열 을 옮 겨 다 니 며 첫 번 째 는 등 보다 크 고 잡 히 지 않 을 확률 을 찾 습 니 다. 수출 금액 만 있 으 면 된다.
AC 코드:
#include   
#include   
#include   
using namespace std;  
  
  
float dp[10110];  
int ww[110];  
float vv[110];  
  
int main (){  
    int t;  
    scanf ("%d",&t);  
    while (t--){  
        float v;  
        int n;  
        int sum=0;  
      
      
        scanf ("%f%d",&v,&n);  
        v=1-v;  
        for (int i=0;i=ww[i];j--){  
                dp[j]=max(dp[j],dp[j-ww[i]]*vv[i]);  
            }  
        }  
          
        for (int i=sum;i>=0;i--){//           
            if(dp[i]>=v){  
                printf ("%d
",i); break; } } } return 0; }

완전 가방
  완전 가방 과 01 가방 의 차 이 는 무 종 물체 가 무한 개 라 는 것 이다.
  상태 전이 방정식 은 dp [i] [v] = max {dp [i - 1] [v - k * c [i]] + k * w [i] | 0 < = k < = n [i]} 이다.
여기 와 01 가방 의 차 이 는 안쪽 순환 순서 입 니 다. 
지금 중요 한 것 은 왜 완전히 가방 을 이렇게 쓸 수 있 느 냐 는 것 이다.다음 에 우리 가 먼저 기억 해 보 자. 01 가방 역순 의 원인 은?max 의 두 가지 가 전 상태 값 이기 위해 서 입 니 다.그럼 여기, 우 리 는 순서대로 쓰 겠 습 니 다. 여기 max 의 두 가 지 는 당연히 현재 상태의 값 입 니 다. 왜 요?가방 마다 무한 하기 때문이다.우리 가 i 를 1 에서 N 으로 순환 할 때 f [v] 는 용량 이 v 가 앞의 i 가지 가방 에서 얻 은 가 치 를 나타 낸다. 여기 서 우리 가 추가 해 야 할 것 은 앞의 가방 이 아니 라 현재 가방 이다.그래서 우리 가 고려 해 야 할 것 은 당연히 현재 상태 다.
HDU1114   http://acm.hdu.edu.cn/showproblem.php?pid=1114
제목: 어떤 사람 은 저금통 (동전 저장) 이 있 는데 비 어 있 을 때 E 가 무 겁 고 돈 이 가득 차 면 F 가 무 겁 습 니 다.지금 그 는 항 아 리 를 돈 으로 가득 채 워 동전 의 종류 와 무 게 를 주 고 저금통 이 적어도 얼 마 를 저축 할 수 있 는 지 계산 했다.
완전 가방 최소 화 
AC 코드:
#include   
#include   
#include   
using namespace std;  
int dp[10100];  
int vv[510];  
int ww[510];  
int main (){  
    const int maxinf=0x3f3f3f3f;  
    int t;  
    scanf ("%d",&t);  
    while (t--){  
        int low,hight;  
        scanf("%d%d",&low,&hight);  
        int weight=hight-low;  
        int n;  
        scanf ("%d",&n);  
        for (int i=0;i

  HDU1248   http://acm.hdu.edu.cn/showproblem.php?pid=1248
AC 코드:
#include   
#include   
#include   
using namespace std;  
  
int dp[10010];  
int vv[3]={150,200,350};  
int main (){  
    int T;  
    scanf ("%d",&T);  
    while (T--){  
        int m;  
        scanf ("%d",&m);  
        memset(dp,0,sizeof(dp));  
        for (int i=0;i<3;i++){  
            for (int j=vv[i];j<=m;j++){  
                dp[j]=max(dp[j],dp[j-vv[i]]+vv[i]);  
            }  
        }  
        printf ("%d
",m-dp[m]); } return 0; }

멀 티 백 팩
다 중 가방 과 01 가방 과 완전 가방 의 차 이 는 각 물체 의 개수 가 제한 되 어 있다 는 것 이다.
저희 가 01 백 팩 으로 볼 수 있어 요. 그 사상 은 n 개의 물체 X 를 n 개의 같은 독립 물체 로 보 는 것 이다.
 HDU2191  http://acm.hdu.edu.cn/showproblem.php?pid=2191
AC 코드:
#include   
#include   
#include   
using namespace std;  
int dp[110];  
int vv[20020];  
int ww[20020];  
  
int main (){  
    int t;  
    scanf ("%d",&t);  
    while (t--){  
        int n,m;  
        scanf ("%d%d",&n,&m);  
        int len=0;  
        while (m--){  
            int p,h,c;  
            scanf ("%d%d%d",&p,&h,&c);  
            while (c--){  
                vv[len]=p;  
                ww[len]=h;  
                len++;  
            }  
        }  
          
        memset(dp,0,sizeof(dp));  
        for (int i=0;i=vv[i];j--){  
                dp[j]=max(dp[j],dp[j-vv[i]]+ww[i]);  
            }  
        }  
        printf ("%d
",dp[n]); } return 0; }

좋은 웹페이지 즐겨찾기