(暴力+各种算法)hihoCoder - 1353 满减优惠

原题链接:

http://hihocoder.com/problemset/problem/1353


题意:

给你一个数列和一个m,从数列里选任意的数,使他们的和大于等于m又是最小,输出这个和。如果不存在输出-1。


分析:

这题一上去,感觉是贪心,然后排个序从大加,加到大于等于m就跳出,交一发直接WA了。然后感觉是二分,枚举m到sum,每次找到小于m最近的数,然后减去这个数。WA了6发,不断地测试数据,一直能找到数据过不了,最终放弃了这种算法,写了一个dfs,20!的复杂度,抱着玩的心态交了一发,果断超时。
但是总觉得这题肯定很简单,最终实在不想想了,结果就看了一下大神的代码,崩溃了,什么算法都有。。
对比一下别人的代码,同样是dfs,人家就是O(2^n),其实dp也应该更加容易想到,复杂度还比dfs低。枚举m到sum,跑01背包就行了。


代码:

贪心WA:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 #include<map>
 7 #include<algorithm>
 8 #include<string>
 9 #include<queue>
10 #include<cmath>
11 #include<stack>
12 #include<cctype>
13 #include<list>
14 
15 
16 #define ll long long
17 #define ull unsigned long long
18 #define VNAME(name) (#name)
19 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
20 #define SI(a) cin>>(a)
21 #define SII(a,b) cin>>(a)>>(b)
22 #define PI(a) cout<<(a)
23 #define PIE(a) cout<<(a)<<endl
24 #define MST(a) memset((a),0,sizeof((a)))
25 
26 using namespace std;
27 
28 const int maxn = 110;
29 const int inf = 1 << 30;
30 int num[maxn];
31 
32 int main() {
33     iostream::sync_with_stdio(false);
34 
35 #ifndef ONLINE_JUDGE
36     freopen("in.txt", "r", stdin);
37     //freopen("out.txt","w",stdout);
38 #endif
39     int n, m;
40     while(SII(n, m)) {
41         int sum = 0;
42         for(int i = 0; i < n; i++) {
43             SI(num[i]);
44 
45         }
46         sort(num, num + n);
47         for(int i = 0; i < n; i++) {
48             sum += num[i];
49             if(sum >= m) {
50                 break;
51             }
52         }
53         if(sum<m){
54             puts("-1");
55         }
56         else{
57             PIE(sum);
58         }
59     }
60     return 0;
61 }
View Code

二分WA:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 #include<map>
 7 #include<algorithm>
 8 #include<string>
 9 #include<queue>
10 #include<cmath>
11 #include<stack>
12 #include<cctype>
13 #include<list>
14 
15 
16 #define ll long long
17 #define ull unsigned long long
18 #define VNAME(name) (#name)
19 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
20 #define SI(a) cin>>(a)
21 #define SII(a,b) cin>>(a)>>(b)
22 #define PI(a) cout<<(a)
23 #define PIE(a) cout<<(a)<<endl
24 #define MST(a) memset((a),0,sizeof((a)))
25 
26 using namespace std;
27 
28 const int maxn = 21;
29 const int inf = 1 << 30;
30 int num[maxn];
31 int n,m;
32 
33 int main() {
34     iostream::sync_with_stdio(false);
35 
36 #ifndef ONLINE_JUDGE
37     //freopen("in.txt", "r", stdin);
38     //freopen("out.txt","w",stdout);
39 #endif
40 
41     while(SII(n, m)) {
42         int sum = 0;
43         for(int i = 0; i < n; i++) {
44             SI(num[i]);
45             sum+=num[i];
46         }
47         if(sum<m){
48             puts("-1");
49             continue;
50         }
51         int tmp[maxn];
52         for(int i=m;i<=sum;i++){
53             int x=i;
54             int flag=0;
55             for(int j=0;j<n;j++){
56                 tmp[j]=num[j];
57             }
58             while(1){
59                 sort(tmp,tmp+n);
60                 int d=lower_bound(tmp,tmp+n,x)-tmp;
61                 if(tmp[d]==x){
62                     flag=1;
63                     PIE(i);
64                     break;
65                 }
66                 else{
67                     if(d==0){
68                         break;
69                     }
70                     else{
71                         x-=tmp[d-1];
72                         tmp[d-1]=inf;
73                     }
74                 }
75                 //PIE(x);
76             }
77             if(flag)break;
78 
79         }
80 
81     }
82     return 0;
83 }
View Code

dfsTLE:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 #include<map>
 7 #include<algorithm>
 8 #include<string>
 9 #include<queue>
10 #include<cmath>
11 #include<stack>
12 #include<cctype>
13 #include<list>
14 
15 
16 #define ll long long
17 #define ull unsigned long long
18 #define VNAME(name) (#name)
19 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
20 #define SI(a) cin>>(a)
21 #define SII(a,b) cin>>(a)>>(b)
22 #define PI(a) cout<<(a)
23 #define PIE(a) cout<<(a)<<endl
24 #define MST(a) memset((a),0,sizeof((a)))
25 
26 using namespace std;
27 
28 const int maxn = 21;
29 const int inf = 1 << 30;
30 int num[maxn];
31 int vis[maxn];
32 int ans=inf;
33 int n, m;
34 bool flag;
35 void dfs(int s,int res){
36     if(s>n)return ;
37     if(s<=n&&res>=m){
38         ans=min(res,ans);
39         flag=1;
40         return ;
41     }
42 
43     for(int i=0;i<n;i++){
44         if(!vis[i]){
45             vis[i]=true;
46             dfs(s+1,res+num[i]);
47             vis[i]=false;
48         }
49 
50     }
51 }
52 
53 int main() {
54     iostream::sync_with_stdio(false);
55 
56 #ifndef ONLINE_JUDGE
57     freopen("in.txt", "r", stdin);
58     //freopen("out.txt","w",stdout);
59 #endif
60 
61     while(SII(n, m)) {
62         MST(vis);
63         flag=0;
64         int sum = 0;
65         for(int i = 0; i < n; i++) {
66             SI(num[i]);
67         }
68         dfs(0,0);
69         if(flag){
70             PIE(ans);
71         }
72         else{
73             puts("-1");
74         }
75     }
76     return 0;
77 }
View Code

dfsAC:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 #include<map>
 7 #include<algorithm>
 8 #include<string>
 9 #include<queue>
10 #include<cmath>
11 #include<stack>
12 #include<cctype>
13 #include<list>
14 
15 
16 #define ll long long
17 #define ull unsigned long long
18 #define VNAME(name) (#name)
19 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
20 #define SI(a) cin>>(a)
21 #define SII(a,b) cin>>(a)>>(b)
22 #define PI(a) cout<<(a)
23 #define PIE(a) cout<<(a)<<endl
24 #define MST(a) memset((a),0,sizeof((a)))
25 
26 using namespace std;
27 
28 const int maxn = 21;
29 const int inf = 1 << 30;
30 int num[maxn];
31 int n, m;
32 int ans;
33 void dfs(int p, int tol) {
34     if(p == n) {
35         if(tol >= m)ans = min(ans, tol);
36         return;
37     }
38     dfs(p + 1, tol + num[p]);
39     dfs(p + 1, tol);
40 }
41 
42 int main() {
43     iostream::sync_with_stdio(false);
44 
45 #ifndef ONLINE_JUDGE
46     freopen("in.txt", "r", stdin);
47     //freopen("out.txt","w",stdout);
48 #endif
49 
50     while(SII(n, m)) {
51         int sum = 0;
52         ans = 0;
53         for(int i = 0; i < n; i++) {
54             SI(num[i]);
55             sum += num[i];
56         }
57         if(sum < m) {
58             puts("-1");
59             continue;
60         }
61         ans = sum;
62         dfs(0, 0);
63         PIE(ans);
64     }
65     return 0;
66 }

dpAC:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 #include<set>
 6 #include<map>
 7 #include<algorithm>
 8 #include<string>
 9 #include<queue>
10 #include<cmath>
11 #include<stack>
12 #include<cctype>
13 #include<list>
14 
15 
16 #define ll long long
17 #define ull unsigned long long
18 #define VNAME(name) (#name)
19 #define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
20 #define SI(a) cin>>(a)
21 #define SII(a,b) cin>>(a)>>(b)
22 #define PI(a) cout<<(a)
23 #define PIE(a) cout<<(a)<<endl
24 #define MST(a) memset((a),0,sizeof((a)))
25 
26 using namespace std;
27 
28 const int maxn = 21;
29 const int inf = 1 << 30;
30 int num[maxn];
31 int dp[101][101];
32 int n, m;
33 int ans;
34 
35 
36 
37 int main() {
38     iostream::sync_with_stdio(false);
39 
40 #ifndef ONLINE_JUDGE
41     freopen("in.txt", "r", stdin);
42     //freopen("out.txt","w",stdout);
43 #endif
44 
45     while(SII(n, m)) {
46         int sum = 0;
47         ans = 0;
48         for(int i = 0; i < n; i++) {
49             SI(num[i]);
50             sum += num[i];
51         }
52         if(sum < m) {
53             puts("-1");
54             continue;
55         }
56         for(int i=m;i<=sum;i++){
57             memset(dp,0,sizeof(dp));
58             for(int j=n-1;j>=0;j--){
59                 for(int k=0;k<=i;k++){
60                     if(k<num[j]){
61                         dp[j][k]=dp[j+1][k];
62                     }
63                     else{
64                         dp[j][k]=max(dp[j+1][k],dp[j+1][k-num[j]]+num[j]);
65                     }
66                 }
67             }
68             if(dp[0][i]==i){
69                 PIE(i);
70                 break;
71             }
72         }
73     }
74     return 0;
75 }

hiho第一名代码,感觉像是dfs的非递归形式:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <map>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <cstdlib>
 9 #include <vector>
10 #include <set>
11 #include <assert.h>
12 using namespace std;
13 
14 
15 #define N 100020
16 #define M 100200
17 #define eps 1e-12
18 #define inf 0x3f3f3f3f
19 #define mod 110119
20 #define LL long long
21 #define ls (i << 1)
22 #define rs (ls | 1)
23 #define md (ll + rr >> 1)
24 #define lson ll, md, ls
25 #define rson md + 1, rr, rs
26 #define MP make_pair
27 #define pii pair<int, int>
28 #define ui unsigned int
29 #define fi first
30 #define se second
31 #define pll pair<LL, LL>
32 #define pdi pair<double, int>
33 
34 int n, a[N], X;
35 
36 
37 int main() {
38     scanf("%d%d", &n, &X);
39     int sum = 0;
40     for(int i = 0; i < n; ++i) {
41         scanf("%d", &a[i]);
42         sum += a[i];
43     }
44     if(sum < X) {
45         puts("-1");
46         return 0;
47     }
48     int ans = inf;
49     for(int s = 1; s < (1 << n); ++s) {
50         int t = 0;
51         for(int j = 0; j < n; ++j) {
52             if(s >> j & 1) {
53                 t += a[j];
54             }
55         }
56         if(t >= X) ans = min(ans, t);
57     }
58     printf("%d\n", ans);
59     return 0;
60 }
View Code

 

 

转载于:https://www.cnblogs.com/tak-fate/p/5765969.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值