原題鏈接:
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;
}