Vijos P1159 岳麓山上打水

P1159岳麓山上打水
Accepted

描述

今天天气好晴朗,处处好风光,好风光!蝴蝶儿忙啊,蜜蜂也忙,信息组的同学们更加忙。最近,由于XX原因,大家不得不到岳麓山去提水。55555555~,好累啊。

信息组有一个容量为q升的大缸,由于大家都很自觉,不愿意浪费水,所以每次都会刚好把缸盛满。但是,信息组并没有桶子(或者瓢)来舀水,作为组内的生活委员,你必须肩负重任,到新一佳去买桶子。

新一佳有p种桶子,每种桶子都有无穷多个^_^,且价钱一样。由于大家都很节约,所以你必须尽量少买桶子。如果有多种方案,你必须选择“更小”的那种方案,即:把这两个方案的集合(不同大小的桶子组成)按升序排序,比较第一个桶,选择第一个桶容积较小的一个。如果第一个桶相同,比较第二个桶,也按上面的方法选择。否则继续这样的比较,直到相比较的两个桶不一致为止。例如,集合{3,5,7,三} 比集合 {3,6,7,8} 要好。

为了把缸装满水,大家可以先从岳麓山的井里把桶装满水提回来,然后倒进缸里。为了不十分麻烦或者浪费宝贵的水资源,大家决不把缸里的水倒出来或者把桶里的水倒掉,也不会把桶里的水再倒回井中,(这样会污染井水)。当然,一个桶可以使用多次。例如,用一个容积为 1 升的桶可以将任意容量的大缸装满水。而其它的组合就要麻烦些。

格式

输入格式

第1行1个数q(q<=20000)。

第2行1个数p(p<=100)。

接下来p行,每行一个数,依次为每个桶的容积。

输出格式

共1行,每两个数间用空格分隔,第1个数k为最少的桶的数量,接下来k个数从小到大输出每个桶的容量。

样例1

样例输入1[复制]

16
3
3
5
7

样例输出1[复制]

2 3 5

限制

各个测试点1s

来源

From facer


本来想着只是一个完全背包,找一下路径即可,然后发现找到的路径不是字典序最小的,

然后想着路径肯定不会特别多,所以先完全背包一下,然后找路径,然后发现跑不完……

然后就各种优化,各种wa。。。。。。


后来看了一下别人的题解,原来是DFSID,,,也就是在深度比较小的地方一定有最优解,所以DFS复杂度很高,那么每次枚举深度,从小到大,在规定时间一定会找到最优解


那么这个题就可以枚举每次用了几个桶,从1~n,然后DFS从n个桶中选出i个,然后完全背包这i个桶即可,,,

 
       

评测结果

编译成功

测试数据 #0: Accepted, time = 0 ms, mem = 3100 KiB, score = 10

测试数据 #1: Accepted, time = 15 ms, mem = 3104 KiB, score = 10

测试数据 #2: Accepted, time = 0 ms, mem = 3104 KiB, score = 10

测试数据 #3: Accepted, time = 0 ms, mem = 3100 KiB, score = 10

测试数据 #4: Accepted, time = 0 ms, mem = 3100 KiB, score = 10

测试数据 #5: Accepted, time = 0 ms, mem = 3100 KiB, score = 10

测试数据 #6: Accepted, time = 546 ms, mem = 3104 KiB, score = 10

测试数据 #7: Accepted, time = 46 ms, mem = 3104 KiB, score = 10

测试数据 #8: Accepted, time = 31 ms, mem = 3104 KiB, score = 10

测试数据 #9: Accepted, time = 640 ms, mem = 3100 KiB, score = 10

Accepted, time = 1278 ms, mem = 3104 KiB, score = 100


代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn (200000 + 20)
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
using namespace std;
typedef long long int LLI;

int dp[maxn];
int pack[maxn],cnt = 1;
int a[maxn];
bool flag[maxn],ll = false;
int q,n;

bool solve() {
    memset(dp,0,sizeof(dp));
    for(int i = 1; i < cnt; i ++) {
        for(int j = pack[i]; j <= q; j ++) {
            dp[j] = max(dp[j - pack[i]] + pack[i],dp[j]);
        }
    }
    if(dp[q] == q)  return  true;
    return false;
}

void dfs(int p,int lim) {
    if(p >= lim) {
        if(solve()) ll = true;
        return;
    }
    for(int i = 1; i <= n; i ++) {
        if(flag[i] == true)    continue;
        flag[i] = true;
        pack[cnt ++] = a[i];
        dfs(p + 1,lim);
        if(ll == true)  return;
        cnt --;
        flag[i] = false;
    }
}

int main() {
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    scanf("%d%d",&q,&n);
    for(int i = 1; i <= n; i ++)    scanf("%d",&a[i]);
    memset(flag,false,sizeof(flag));
    sort(a + 1,a + n + 1);
    for(int i = 1; i <= n; i ++) {
        dfs(0,i);
        if(ll == true) {
            printf("%d ",cnt - 1);
            for(int j = 1; j < cnt - 1; j ++) {
                printf("%d ",pack[j]);
            }
            printf("%d\n",pack[cnt - 1]);
            break;
        }
    }
    return 0;
}

=========================================================================

另外附上我各种wa的代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define maxn (200000 + 20)
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
using namespace std;
typedef long long int LLI;

int a[maxn];
int dp[110][maxn];
int vec[maxn],v = 0;
int re[maxn],cnt = 0;
int Copy[maxn];

bool Compare(int p) {
    if(p > cnt) return true;
    for(int i = 0; i < p && i < cnt; i ++) {
        if(re[i] > Copy[i]) return false;
    }
    if(p < cnt) return false;
    return true;
}

void dfs(int x,int y) {
//    printf("%d %d %d %d %d\n",x,y,dp[x][y],dp[x - 1][y],dp[x][y - a[x]] + a[x]);
    if(x < 1 || y < 0)  {
        for(int i = 0; i < v; i ++)   Copy[i] = vec[i];
        sort(Copy,Copy + v);
        int p = unique(Copy,Copy + v) - Copy;
//        printf("------ ");
//        for(int i = 0; i < p; i++) {
//            printf("%d ",Copy[i]);
//        }
//        printf("\n");
        if(cnt == 0 || !Compare(p)) {
            for(int i = 0; i < p; i ++)
                re[i] = Copy[i];
            cnt = p;
        }
        return;
    }
    if(dp[x][y] == dp[x - 1][y]) {
        dfs(x - 1,y);
    }
    if(dp[x][y] == dp[x][y - a[x]] + a[x]) {
        vec[v ++] = a[x];
        dfs(x,y - a[x]);
        v --;
    }
}

int main() {
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    int n,q,x;
    scanf("%d%d",&q,&n);
    for(int i = 1; i <= n; i ++)
        scanf("%d",&a[i]);
    sort(a + 1,a + n + 1);
    for(int i = 1; i <= n; i ++) {
        for(int j = 0; j < a[i]; j ++)
            dp[i][j] = dp[i - 1][j];
        for(int j = a[i]; j <= q; j ++)
            dp[i][j] = max(dp[i - 1][j],dp[i][j - a[i]] + a[i]);
        if(dp[i - 1][q] == q) {
            x = i;
            break;
        }
        else    x = i;
    }
    dfs(x,q);
    printf("%d ",cnt);
    for(int i = 0; i < cnt - 1; i ++)
        printf("%d ",re[i]);
    printf("%d\n",re[cnt - 1]);
    return 0;
}


你可能感兴趣的:(动态规划)