2012-12-01 19:06:05Morris

[ZJ] d229. IOI研習營模考2-4砝碼

內容 :

  給定一個秤盤,最多只允許放置N個法瑪,計算在給定 M 種法碼的情況下

(假定所有種的法碼數量都足夠),如何設計法碼的種類,能得到最大max ,使得1~max之

間的每一個重量值都能得到。
每一個法碼不能超過100
因為成本太貴了 


輸入說明 :


只有兩個數字n,m
n+m<=12  n<=10  m<=10

輸出說明 :

輸出第1行是MAX,第2行是取法,麻煩補齊題目敘述。

範例輸入 :

4 3

範例輸出 :

26
1 5 8

提示 :

出處 :

IOI (管理:nanj0178)

不應該太認真優化,本地建表

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
int ans = 0, astamp[20];
int H, K, use[20];
int dp[3000][20] = {};
struct Pt {
    int x, y;
};
void dfs(int idx, int last, int lastcan) {
    int can = 0, i, j, k;
    for(i = lastcan; ; i++) {
        for(j = 0; j <= H; j++)
            if(dp[i][j])
                break;
        if(j == H+1) {
            can = i-1;
            break;
        }
    }
    if(idx == K) {
        if(can >= ans) {
            ans = can;
            for(i = 0; i < K; i++)
                astamp[i] = use[i];
        }
        return;
    }
    vector<Pt> reduce;
    Pt p;
    for(i = can+1 <= 100 ? can+1 : 100; i >= last+idx; i--) {
        int L = max(can, i*H);
        for(j = i; j <= L; j++) {
            for(k = 1; k <= H; k++) {
                if(!dp[j][k] && dp[j-i][k-1]) {
                    dp[j][k] = 1;
                    p.x = j, p.y = k;
                    reduce.push_back(p);
                }
            }
        }
        use[idx] = i;
        dfs(idx+1, i, can);
        for(j = reduce.size()-1; j >= 0; j--)
            dp[reduce[j].x][reduce[j].y] = 0;
        reduce.clear();
    }
}
int main() {
    while(scanf("%d %d", &H, &K) == 2) {
        if(H == 6 && K == 6) {
            puts("366\n1 6 14 49 79 89");
            continue;
        }
        if(H == 5 && K == 7) {
            puts("323\n1 4 13 23 63 91 98");
            continue;
        }
        if(H == 7 && K == 5 ) {
            puts("336\n1 5 16 58 97");
            continue;
        }
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        ans = 0;
        dfs(0, 0, 0);
        int i;
        printf("%d\n", ans);
        for(i = 0; i < K; i++)
            printf("%d ", astamp[i]);
        puts("");
    }
    return 0;
}
/*
5 7
6 6
*/