贪心+huffman编码+模拟退火+分治
A - 今年暑假不AC
#include<iostream> #include<string.h> #include<algorithm> #include<map> #include<stdio.h> #define MAXN 3000 using namespace std; struct node { int start,end; }record[MAXN]; //结束时间早的优先 bool cmp(const node& a,const node& b){ return a.end<b.end; } int main() { int n; while(1) { cin>>n; if(n==0)break; for(int i=0;i<n;++i) cin>>record[i].start>>record[i].end; sort(record,record+n,cmp); int count=0; int lastend=-1; for(int i=0;i<n;++i) { if(record[i].start>=lastend) { count++; lastend = record[i].end; } } cout<<count<<endl; } return 0; }
B - 迷瘴
我可烦死这道题了,精度哪里老是死,气死了
#include<iostream> #include<string.h> #include<algorithm> #include<map> #include<stdio.h> #define MAXN 105 using namespace std; int record[MAXN]; int n,V,W; struct node { float e;//分子 int v;//分母 }med; int main() { int C;cin>>C; while(C--) { cin>>n>>V>>W; for(int ii=0;ii<n;++ii) cin>>record[ii]; sort(record,record+n); int i;med.e=0,med.v=0; for(i=0;i<n;++i) { if((float)(med.e*med.v+record[i]*1.0/100*V)*1.0/(med.v+V)>W*1.0/100) { printf("%d %.2lf\n",med.v,med.e); break; } else { med.e =(float)(med.v*med.e+record[i]*1.0/100*V)*1.0/(med.v+V);;//分子 med.v +=V; } } if(i==n) printf("%d %.2lf\n",med.v,med.e); } return 0; }
Entropy POJ - 1521
#include<iostream> #include<algorithm> #include<queue> #include<stdio.h> #define ll long long using namespace std; int main() { string s; // 优先队列,最小的在最前面,优先队列默认是从大到小排序 while(getline(cin,s)&&s!="END") { int t=1; sort(s.begin(),s.end()); priority_queue<int,vector<int>,greater<int> >Q; for(int i=1;i<s.length();++i) { if(s[i]!=s[i-1]) { Q.push(t); t = 1; //统计每一个字符出现的频次,加入优先队列 } else t++; } Q.push(t);//最后一个没得比较,直接加入队列 int ans=0; while(Q.size()>1) { int a = Q.top();Q.pop(); int b= Q.top();Q.pop(); //cout<<a<<","<<b<<","<<ans<<endl; ans += a+b; Q.push(a+b); } if(!ans) ans=s.length(); while(!Q.empty()) Q.pop(); int ascii=s.length()*8; printf("%d %d %.1f\n",ascii,ans,(ascii*1.0)/(ans*1.0)); } return 0; }
Strange fuction HDU - 2899
#include<iostream> #include<algorithm> #include<queue> #include<stdio.h> #include<math.h> #define ll long long using namespace std; const double eps=1e-8; double y; double func(double x) { return 6*pow(x,7.0)+8*pow(x,6.0)+7*pow(x,3.0)+5*pow(x,2.0)-y*x; } double solve() { double T = 100; double delta = 0.98; double x=50.0; double now=func(x); double ans=now; while(T>eps) { int f[2]={1,-1}; double newx = x+f[rand()%2]*T; if(newx>=0&&newx<=100) { double next = func(newx); ans = min(ans,next); if(now - next>eps) { x = newx; now = next; } } T *=delta; return ans; } int main() { int cas; scanf("%d",&cas); while(cas--) { scanf("%lf",&y); printf("%.4f\n",solve()); } return 0; }
Doing Homework again HDU - 1789
- 第一种排序按截止日期从小到大排序,以保证可以完成最多的作业,截止日期相同的按照惩罚从大到小排序,以保证惩罚最小
- 第二种排序利用优先队列,按照惩罚从小到大排序,将第一个排序法中取出的作业放到这个优先队列中。
- 发生超时,从优先队列中取出第一个数用它的惩罚与当前的比较,如果队列中的惩罚比他小,则把这个数加入队列,原来的作业放弃,否则这个作业就放弃
#include<iostream> #include<algorithm> #include<queue> #include<stdio.h> #include<math.h> #define ll long long using namespace std; const int M=1004; struct node { int deadline; int reduced_score; }course[M]; int N; bool cmp(node &a,node &b) { if(a.deadline==b.deadline) return a.reduced_score>b.reduced_score; else return a.deadline<b.deadline; } struct cmp2 { bool operator()(node a,node b) { return a.reduced_score>b.reduced_score; } }; int solve() { sort(course,course+N,cmp); int red_sum=0; int TAG=1; priority_queue<node,vector<node>,cmp2> q; for(int i=0;i<N;++i) { if(course[i].deadline<TAG) { if(q.top().reduced_score<course[i].reduced_score) { red_sum+=q.top().reduced_score; q.pop(); q.push(course[i]); } else red_sum+=course[i].reduced_score; } else { q.push(course[i]); TAG++; } } return red_sum; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&N); for(int i=0;i<N;++i) { scanf("%d",&course[i].deadline); } for(int i=0;i<N;++i) { scanf("%d",&course[i].reduced_score); } printf("%d\n",solve()); } return 0; }
饭卡 HDU - 2546
01背包,从小到大排序,用前n-1个填m-5的背包
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define MAX 1007 using namespace std; int price[MAX],dp[MAX],m,n; int main() { while(~scanf("%d",&n)&&n!=0) { for(int i=0;i<n;++i) { cin>>price[i]; } cin>>m; if(m<5) { cout<<m<<endl; } else { sort(price,price+n); memset(dp,0,sizeof(dp)); for(int i=0;i<n-1;++i) { for(int j=m-5;j>=price[i];--j) { dp[j]=max(dp[j],dp[j-price[i]]+price[i]); } } cout<<m-dp[m-5]-price[n-1]<<endl; } } return 0; }
coins HDU - 3348
这里一开始就给出了有序的从小到大的数值。先算如何让硬币最少的问题,如何让硬币最多可以转化为计算sum(所有的硬币总价钱)-p(商品的价钱)时,硬币如何最少。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define MAX 1000007 using namespace std; int a[5],p,T; int b[5]={1,5,10,50,100}; bool cmp(int &a,int &b) { return a>b; } int Count(int p) { int t=0,min_t=0; for(int i=4;i>=0;--i) { min_t=min(p/b[i],a[i]); p -=b[i]*min_t; t+=min_t; if(p==0) break; } if(p==0) return t; else return -1; } int main() { scanf("%d",&T); while(T--) { cin>>p; int sum=0,coin=0; for(int i=0;i<5;++i) { cin>>a[i]; sum+=a[i]*b[i]; coin+=a[i]; } int res=Count(p); if(res==-1) cout<<"-1 -1"<<endl; else cout<<res<<" "<<coin-Count(sum-p)<<endl; } return 0; }
#handwriting
- 任一面值的硬币,大于比他小的所有硬币的面值之和。可以用贪心法,例如以2的倍数递增的1、2、4、8等,这样的面值就符合条件