Allocation
题意
N个房子出售,每个卖Ai刀,现有B刀资金,求最多买多少个。
思路
贪心,排序后从小到大买
代码
#include<bits/stdc++.h> using namespace std; const int MAX=1e5+5; int a[MAX]; int main() { int T,cas=0; scanf("%d",&T); while(T--) { int n,b,res=0; scanf("%d%d",&n,&b); for(int i=0;i<n;i++) scanf("%d",&a[i]); sort(a,a+n); for(int i=0;i<n;i++) { if(a[i]>b)break; b-=a[i]; res++; } printf("Case #%d: %d\n",++cas,res); } }
Plates
题意
有n摞盘子,每一摞有k个,每个盘子有一定价值,现在要选p个盘子,要求每次只能选一摞的从上到下的一部分,求如何选使得总价值最大
思路
DP,dp[i][j] 表示前i摞中共选j个可得的最大价值,转移枚举当前摞选m个(选前缀),然后由 dp[i-1][j-m] 转移而来
代码
#include<bits/stdc++.h> using namespace std; const int MAX=1505; int a[MAX][MAX],pre[MAX][MAX],dp[MAX][MAX]; int main() { int T,cas=0; scanf("%d",&T); while(T--) { int n,p,m; scanf("%d%d%d",&n,&m,&p); memset(dp,0,sizeof dp); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) { scanf("%d",&a[i][j]); pre[i][j]=pre[i][j-1]+a[i][j]; } for(int i=1; i<=n; i++) for(int j=0; j<=min(i*m,p); j++) for(int k=0; k<=min(j,m);k++) dp[i][j]=max(dp[i][j],dp[i-1][j-k]+pre[i][k]); printf("Case #%d: %d\n",++cas,dp[n][p]); } }
Workout
题意
给一个单调递增序列,有n个数,设D值为此序列每个数与相邻数的差的最大值,现在可以在保证序列单调增的情况下,在此序列任意位置插入任意大小的k个数,求如何使得此序列D值最小,求出最小D值。
思路
容易想到,可以在两个数中间插a个数,使得两者差变为原来的a分之一(向上取整),先处理出原序列所有差,然后二分答案,再通过上述结论检测此答案是否可行,最后得到最小值。
代码
#include<bits/stdc++.h> using namespace std; const int MAX=1e5+5; int n,k,a[MAX],ch[MAX]; bool check(int x) { int tot=k; for(int i=1; i<n; i++) { if(ch[i]<=x)continue; for(int j=1;; j++) { int cur=(ch[i]+j)/(j+1); if(cur<=x) { if(j<=tot)tot-=j; else return 0; break; } } } return 1; } int main() { int T,cas=0; scanf("%d",&T); while(T--) { int L=1,R=-1,res; scanf("%d%d",&n,&k); for(int i=0; i<n; i++) scanf("%d",&a[i]); for(int i=1; i<n; i++) ch[i]=a[i]-a[i-1],R=max(R,ch[i]); while(L<=R) { int mid=(L+R)>>1; if(check(mid)) { res=mid; R=mid-1; } else L=mid+1; } printf("Case #%d: %d\n",++cas,res); } }
Bundling
题意
给n个字符串,要求分成大小为k的若干组(n是k的倍数),每组的得分为该组所有字符串的最长公共前缀长度。求如何使得得分最大化,求出最大得分。
思路
显然公共前缀越长越好,所以贪心,找公共前缀最长的能分成一组的就分成一组,建一棵字典树,记录以某前缀开头的字符串数量。然后在字典树上贪心寻找尽可能深的,足够分成一组的前缀(即寻找以此前缀开头的字符串数量大于等于k的前缀),然后用深度更新答案,再返回已经用过的数量给父亲,更新父亲的数量。
代码
#include<bits/stdc++.h> using namespace std; const int MAX=2e6+6; typedef long long ll; int nxt[MAX][26],sum[MAX],cnt,n,k; ll res; char ss[MAX]; void ins(char *s) { int p=0,len=strlen(s); sum[p]++; for (int i=0; i<len; i++) { int c=s[i]-'A'; if(!nxt[p][c])nxt[p][c]=++cnt; p=nxt[p][c]; sum[p]++; } } int dfs(int x,int d) { int ssum=0,cur=0; for(int i=0;i<26;i++) if(nxt[x][i]) ssum+=dfs(nxt[x][i],d+1); sum[x]-=ssum; if(sum[x]>=k) { cur=sum[x]/k; res+=d*cur; sum[x]%=k; } return ssum+cur*k; } void init() { memset(nxt,0,sizeof nxt); memset(sum,0,sizeof sum); cnt=0; res=0; } int main() { int T,cas=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&k); init(); for(int i=0;i<n;i++) { scanf("%s",ss); ins(ss); } dfs(0,0); printf("Case #%d: %lld\n",++cas,res); } }
来源:https://www.cnblogs.com/cryingrain/p/12569372.html