原题链接:
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 }