51nod确实是一个好oj,题目质量不错,wa了还放数据,学习算法来说挺好的,这次我做了几个水的贪心,虽然水,但是确实都很典型。
教程链接:http://www.51nod.com/tutorial/list.html
完美字符串
约翰认为字符串的完美度等于它里面所有字母的完美度之和。每个字母的完美度可以由你来分配,不同字母的完美度不同,分别对应一个1-26之间的整数。
约翰不在乎字母大小写。(也就是说字母F和f)的完美度相同。给定一个字符串,输出它的最大可能的完美度。例如:dad,你可以将26分配给d,25分配给a,这样整个字符串完美度为77。
分析: 由排序不等式,出现次数最多的字母显然应该给26。所以这个题目变成了统计每种字母出现的次数了,然后按照出现次数从大到小,依次分配从高到低的权值。这就是最朴素的贪心思想。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<string> 6 #include<algorithm> 7 #include<cctype> 8 #include<cstdlib> 9 using namespace std; 10 const int maxn=27; 11 int a[maxn]; 12 string s; 13 bool cmp(const int a,const int b) 14 { 15 return a>b; 16 } 17 int main() 18 { 19 while(cin>>s) 20 { 21 memset(a,0,sizeof(a)); 22 for(int i=0;i<s.length();i++) 23 a[tolower(s[i])-'a']++; 24 sort(a,a+26,cmp); 25 long long sum=0; 26 int b=26; 27 for(int i=0;i<26;i++) 28 { 29 sum+=a[i]*b; 30 --b; 31 } 32 cout<<sum<<endl; 33 } 34 return 0; 35 }
活动安排问题
有若干个活动,第i个开始时间和结束时间是[Si,fi),只有一个教室,活动之间不能交叠,求最多安排多少个活动?
分析:看似最不对的策略——结束时间越早的活动优先,才是正确的贪心。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 const int maxn=10000+1; 9 typedef struct 10 { 11 int start; 12 int over; 13 }point; 14 point p[maxn]; 15 const int cmp(const point a, const point b) 16 { 17 return a.over<=b.over; 18 } 19 int main() 20 { 21 int n; 22 while(cin>>n) 23 { 24 memset(p,0,sizeof(p)); 25 for(int i=0;i<n;i++) 26 cin>>p[i].start>>p[i].over; 27 sort(p,p+n,cmp); 28 int cnt=1; 29 for(int i=0;i<n;i++) 30 { 31 for(int j=i+1;j<n;j++) 32 { 33 if(p[i].over<=p[j].start) 34 { 35 i=j; 36 cnt++; 37 continue; 38 } 39 } 40 } 41 cout<<cnt<<endl; 42 } 43 return 0; 44 }
活动安排问题二
有若干个活动,第i个开始时间和结束时间是[Si,fi),活动之间不能交叠,要把活动都安排完,至少需要几个教室?
上一题的升级版
分析:如果只需要教室的个数,我们可以把所有开始时间和结束时间排序,遇到开始时间就把厚度加1,遇到结束时间就把厚度减1,显然最初始和最后结束时的厚度是0,在一系列厚度变化的过程中,峰值(最大值)就是最多同时进行的活动数,也是我们至少需要的教室数。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=10000+1; 10 int te[maxn],ts[maxn]; 11 int main() 12 { 13 int n; 14 while(cin>>n) 15 { 16 for(int i=0;i<n;i++) 17 scanf("%d%d",&ts[i],&te[i]); 18 sort(ts,ts+n); 19 sort(te,te+n); 20 int cnt=0; 21 int mx=0,j=0; 22 for(int i=0;i<n;i++) 23 { 24 if(ts[i]<te[j]) 25 { 26 cnt++; 27 if(cnt>mx) 28 mx=cnt; 29 } 30 else if(ts[i]>te[j]) 31 { 32 //cnt--; 33 j++; 34 } 35 else 36 { 37 j++; 38 } 39 } 40 cout<<mx<<endl; 41 } 42 return 0; 43 }
独木舟问题
n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?
分析:按照人的体重排序,最轻的人跟最重的人尽量安排在一条船上,如果超过就安排最重的
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<string> 7 #include<cctype> 8 #include<algorithm> 9 #include<vector> 10 using namespace std; 11 const int maxn=10001; 12 int a[maxn]; 13 bool cmp(long long a,long long b) 14 { 15 return a>b; 16 } 17 int main() 18 { 19 int n; 20 long long m; 21 while(cin>>n) 22 { 23 scanf("%lld",&m); 24 long long x; 25 for(int i=0;i<n;i++) 26 scanf("%lld",&a[i]); 27 sort(a,a+n,cmp); 28 long long cnt=0; 29 int i=0; 30 while(i<n) 31 { 32 if(a[n-1]+a[i]<=m) 33 { 34 cnt++; 35 n--; 36 i++; 37 } 38 else 39 { 40 i++; 41 cnt++; 42 } 43 //cout<<a[i]<<"jk"<<a[n-1-i]<<endl; 44 } 45 //cout<<i<<"io"<<endl; 46 cout<<cnt<<endl; 47 } 48 return 0; 49 }
任务执行顺序
有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i])。
分析:
可以抽象成,从一个整数开始,每次减去a,再加上b (a,b都是正数),要求每次操作都不产生负数。
令a[i] = R[i], b[i] = R[i] – O[i],O[i] < R[i],有0<b[i]<a[i]。 所以尽管每次有减有加,但是加的没有减的多,总数在不断减小。所以——按照b[i]不增的顺序排序,是最“有利”的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cctype> 5 #include<vector> 6 #include<string> 7 #include<cmath> 8 #include<algorithm> 9 using namespace std; 10 const int maxn=100001; 11 long long r[maxn],o[maxn],b[maxn],a[maxn]; 12 bool cmp(long long a,long long b) 13 { 14 return a>b; 15 } 16 int main() 17 { 18 int n; 19 while(cin>>n) 20 { 21 for(int i=0;i<n;i++) 22 scanf("%lld%lld",&r[i],&o[i]); 23 for(int i=0;i<n;i++) 24 { 25 a[i]=r[i]; 26 b[i]=r[i]-o[i]; 27 } 28 sort(b,b+n,cmp); 29 long long mx=0x3fff; 30 long long ans=0; 31 for(int i=0;i<n;i++) 32 { 33 ans-=a[i]; 34 if(ans<mx) 35 mx=ans; 36 ans+=b[i]; 37 } 38 cout<<(0-mx)<<endl; 39 } 40 return 0; 41 }