原题链接:
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 }
二分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 }
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 }
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 ", ans); 59 return 0; 60 }