(暴力+各種算法)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:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
#define SI(a) cin>>(a)
#define SII(a,b) cin>>(a)>>(b)
#define PI(a) cout<<(a)
#define PIE(a) cout<<(a)<<endl
#define MST(a) memset((a),0,sizeof((a)))

using namespace std;

const int maxn = 110;
const int inf = 1 << 30;
int num[maxn];

int main() {
    iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif
    int n, m;
    while(SII(n, m)) {
        int sum = 0;
        for(int i = 0; i < n; i++) {
            SI(num[i]);

        }
        sort(num, num + n);
        for(int i = 0; i < n; i++) {
            sum += num[i];
            if(sum >= m) {
                break;
            }
        }
        if(sum<m){
            puts("-1");
        }
        else{
            PIE(sum);
        }
    }
    return 0;
}

二分WA:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
#define SI(a) cin>>(a)
#define SII(a,b) cin>>(a)>>(b)
#define PI(a) cout<<(a)
#define PIE(a) cout<<(a)<<endl
#define MST(a) memset((a),0,sizeof((a)))

using namespace std;

const int maxn = 21;
const int inf = 1 << 30;
int num[maxn];
int n,m;

int main() {
    iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif

    while(SII(n, m)) {
        int sum = 0;
        for(int i = 0; i < n; i++) {
            SI(num[i]);
            sum+=num[i];
        }
        if(sum<m){
            puts("-1");
            continue;
        }
        int tmp[maxn];
        for(int i=m;i<=sum;i++){
            int x=i;
            int flag=0;
            for(int j=0;j<n;j++){
                tmp[j]=num[j];
            }
            while(1){
                sort(tmp,tmp+n);
                int d=lower_bound(tmp,tmp+n,x)-tmp;
                if(tmp[d]==x){
                    flag=1;
                    PIE(i);
                    break;
                }
                else{
                    if(d==0){
                        break;
                    }
                    else{
                        x-=tmp[d-1];
                        tmp[d-1]=inf;
                    }
                }
                //PIE(x);
            }
            if(flag)break;

        }

    }
    return 0;
}

dfsTLE:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
#define SI(a) cin>>(a)
#define SII(a,b) cin>>(a)>>(b)
#define PI(a) cout<<(a)
#define PIE(a) cout<<(a)<<endl
#define MST(a) memset((a),0,sizeof((a)))

using namespace std;

const int maxn = 21;
const int inf = 1 << 30;
int num[maxn];
int vis[maxn];
int ans=inf;
int n, m;
bool flag;
void dfs(int s,int res){
    if(s>n)return ;
    if(s<=n&&res>=m){
        ans=min(res,ans);
        flag=1;
        return ;
    }

    for(int i=0;i<n;i++){
        if(!vis[i]){
            vis[i]=true;
            dfs(s+1,res+num[i]);
            vis[i]=false;
        }

    }
}

int main() {
    iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif

    while(SII(n, m)) {
        MST(vis);
        flag=0;
        int sum = 0;
        for(int i = 0; i < n; i++) {
            SI(num[i]);
        }
        dfs(0,0);
        if(flag){
            PIE(ans);
        }
        else{
            puts("-1");
        }
    }
    return 0;
}

dfsAC:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
#define SI(a) cin>>(a)
#define SII(a,b) cin>>(a)>>(b)
#define PI(a) cout<<(a)
#define PIE(a) cout<<(a)<<endl
#define MST(a) memset((a),0,sizeof((a)))

using namespace std;

const int maxn = 21;
const int inf = 1 << 30;
int num[maxn];
int n, m;
int ans;
void dfs(int p, int tol) {
    if(p == n) {
        if(tol >= m)ans = min(ans, tol);
        return;
    }
    dfs(p + 1, tol + num[p]);
    dfs(p + 1, tol);
}

int main() {
    iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif

    while(SII(n, m)) {
        int sum = 0;
        ans = 0;
        for(int i = 0; i < n; i++) {
            SI(num[i]);
            sum += num[i];
        }
        if(sum < m) {
            puts("-1");
            continue;
        }
        ans = sum;
        dfs(0, 0);
        PIE(ans);
    }
    return 0;
}

dpAC:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<string>
#include<queue>
#include<cmath>
#include<stack>
#include<cctype>
#include<list>


#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;
#define SI(a) cin>>(a)
#define SII(a,b) cin>>(a)>>(b)
#define PI(a) cout<<(a)
#define PIE(a) cout<<(a)<<endl
#define MST(a) memset((a),0,sizeof((a)))

using namespace std;

const int maxn = 21;
const int inf = 1 << 30;
int num[maxn];
int dp[101][101];
int n, m;
int ans;



int main() {
    iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif

    while(SII(n, m)) {
        int sum = 0;
        ans = 0;
        for(int i = 0; i < n; i++) {
            SI(num[i]);
            sum += num[i];
        }
        if(sum < m) {
            puts("-1");
            continue;
        }
        for(int i=m;i<=sum;i++){
            memset(dp,0,sizeof(dp));
            for(int j=n-1;j>=0;j--){
                for(int k=0;k<=i;k++){
                    if(k<num[j]){
                        dp[j][k]=dp[j+1][k];
                    }
                    else{
                        dp[j][k]=max(dp[j+1][k],dp[j+1][k-num[j]]+num[j]);
                    }
                }
            }
            if(dp[0][i]==i){
                PIE(i);
                break;
            }
        }
    }
    return 0;
}

hiho第一名代碼,感覺像是dfs的非遞歸形式:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <assert.h>
using namespace std;


#define N 100020
#define M 100200
#define eps 1e-12
#define inf 0x3f3f3f3f
#define mod 110119
#define LL long long
#define ls (i << 1)
#define rs (ls | 1)
#define md (ll + rr >> 1)
#define lson ll, md, ls
#define rson md + 1, rr, rs
#define MP make_pair
#define pii pair<int, int>
#define ui unsigned int
#define fi first
#define se second
#define pll pair<LL, LL>
#define pdi pair<double, int>

int n, a[N], X;


int main() {
    scanf("%d%d", &n, &X);
    int sum = 0;
    for(int i = 0; i < n; ++i) {
        scanf("%d", &a[i]);
        sum += a[i];
    }
    if(sum < X) {
        puts("-1");
        return 0;
    }
    int ans = inf;
    for(int s = 1; s < (1 << n); ++s) {
        int t = 0;
        for(int j = 0; j < n; ++j) {
            if(s >> j & 1) {
                t += a[j];
            }
        }
        if(t >= X) ans = min(ans, t);
    }
    printf("%d\n", ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章