Uva11450 Wedding shopping

题目: 链接

有C个商店和M数量的钱,每个商店有若干不同价格的衣服,需要在每个商店都买一件衣服,并且最终花费的钱需要最大(但不大于M),问最多的花费是多少?如果不能在每个店都买一件衣服,那么输出no solution

样例输入

3
100 4
3 8 6 4
2 5 10
4 1 3 3 7
4 50 14 23 8
20 3
3 4 6 8
2 5 10
4 1 3 5 5
5 3
3 6 4 8
2 10 6
4 7 3 1 7

样例输出

75
19
no solution

思路

  • 一个dp问题,假设我们依次在商店0, 1, 2...购买衣服,用g表示当前购买的商店的序号,money表示当前余下的钱。reachable[g][money]数组表示在商店g购买一件衣服后剩余money的数量,其值为true,表示此种状态可以达到,否则该状态不成立,依次填写表格,最后看在第C家商店能否有reachable[C-1][money]=true的状态,有的话找到money最小的那个,即是最多的花费,否则失败。

代码

#include <iostream>
#include <memory.h>
using namespace std;
const int maxm = 205;
const int maxc = 25;
int price[maxm][maxc];
bool reachable[maxc][maxm];  //for i'th garment, whether we can fetch one thing and the remaining monney
int main(){
    freopen("uva_input.txt", "r", stdin);
    freopen("uva_output.txt", "w", stdout);
    int N; scanf("%d", &N);
    //printf("%d", N);
    while(N--){
        int M, C;
        scanf("%d%d", &M, &C);
        for(int i = 0;i < C; ++i){
            scanf("%d", &price[i][0]);
            for(int j = 1; j <= price[i][0]; ++j) scanf("%d", &price[i][j]);
        }
        memset(reachable, false, sizeof(reachable));
        for(int i = 1; i <= price[0][0]; ++i){  //initial condition, for garment 0
            reachable[0][M-price[0][i]] = true;
        }

        for(int g = 1; g < C; ++g){
            for(int money = 0; money <= M; ++money){
                if(reachable[g-1][money]){
                    for(int k = 1; k <= price[g][0]; ++k){
                        reachable[g][money-price[g][k]] = true;
                    }
                }
            }
        }
        int money;
        for(money = 0; money <= M && !reachable[C-1][money]; ++money);  // after C garment, find the reachable solutions
        if(money == M+1) printf("no solution\n");
        else printf("%d\n", M-money);
    }
}

Note:

  • 这里的reachable数组可以优化,因为在计算第g家商店的各状态时,只与从g-1家商店出来后的状态有关,与先前其它状态无关,因此用reachable[2][money]即可表示状态,在各商店购买一件衣服后剩余钱的状态即滚动地在这个row为2的二位数组中记录。

代码

#include <iostream>
#include <memory.h>
using namespace std;
const int maxm = 205;
const int maxc = 25;
int price[maxm][maxc];
bool reachable[2][maxm];  //for i'th garment, whether we can fetch one thing and the remaining monney
int main(){
    freopen("uva_input.txt", "r", stdin);
    freopen("uva_output.txt", "w", stdout);
    int N; scanf("%d", &N);
    //printf("%d", N);
    while(N--){
        int M, C;
        scanf("%d%d", &M, &C);
        for(int i = 0;i < C; ++i){
            scanf("%d", &price[i][0]);
            for(int j = 1; j <= price[i][0]; ++j) scanf("%d", &price[i][j]);
        }
        memset(reachable, false, sizeof(reachable));
        for(int i = 1; i <= price[0][0]; ++i){  //initial condition, for garment 0
            reachable[0][M-price[0][i]] = true;
        }
        int idx = 0;
        for(int g = 1; g < C; ++g){
            memset(reachable[!idx], false, sizeof(reachable[!idx]));
            for(int money = 0; money <= M; ++money){
                if(reachable[idx][money]){
                    for(int k = 1; k <= price[g][0]; ++k){
                        reachable[!idx][money-price[g][k]] = true;
                    }
                }
            }
            idx = !idx;
        }
        int money;
        for(money = 0; money <= M && !reachable[idx][money]; ++money);  // after C garment, find the reachable solutions
        if(money == M+1) printf("no solution\n");
        else printf("%d\n", M-money);
    }
}
posted @ 2020-01-19 21:31  patrolli  阅读(106)  评论(0编辑  收藏  举报