今天天气好晴朗,处处好风光,好风光!蝴蝶儿忙啊,蜜蜂也忙,信息组的同学们更加忙。最近,由于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个数从小到大输出每个桶的容量。
16 3 3 5 7
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;
}