Allocation 简单贪心
Problem
There are N houses for sale. The i-th house costs Ai dollars to buy. You have a budget of B dollars to spend.
What is the maximum number of houses you can buy?
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a single line containing the two integers N and B. The second line contains N integers. The i-th integer is Ai, the cost of the i-th house.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the maximum number of houses you can buy.
简单贪心
#include<iostream>
#include<cstdio>
#include<algorithm>
#define MAXN 100010
using namespace std;
int T,n,b,a[MAXN],iCase;
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&b);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
sort(a,a+n);
int res=0;
for(int i=0;i<n;i++)
if(b>=a[i]){
res++;
b-=a[i];
}
printf("Case #%d: %d\n",++iCase,res);
}
return 0;
}
Plates 多重背包
Problem
Dr. Patel has N stacks of plates. Each stack contains K plates. Each plate has a positive beauty value, describing how beautiful it looks.
Dr. Patel would like to take exactly P plates to use for dinner tonight. If he would like to take a plate in a stack, he must also take all of the plates above it in that stack as well.
Help Dr. Patel pick the P plates that would maximize the total sum of beauty values.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the three integers N, K and P. Then, N lines follow. The i-th line contains K integers, describing the beauty values of each stack of plates from top to bottom.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the maximum total sum of beauty values that Dr. Patel could pick.
类似于多重背包,从 n n n 个筐里总共选 P P P 件物品,每个筐中只允许选择其中一个(或者不选),求最大化价值。
d p [ i ] [ j ] dp[i][j] dp[i][j] 表示前 i i i 个里面总共选了 j j j 个物品,则:
d p [ i ] [ j ] = max ( d p [ i ] [ j ] , d p [ i − 1 ] [ j − w [ k ] ] + v [ i ] [ k ] ) dp[i][j]=\max(dp[i][j],dp[i-1][j-w[k]]+v[i][k]) dp[i][j]=max(dp[i][j],dp[i−1][j−w[k]]+v[i][k])
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 1510
using namespace std;
int T,iCase,n,K,P,cnt,w[MAXN],p[55][35],dp[55][MAXN];
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&K,&P);
for(int i=1;i<=n;i++){
int rp=0;
p[i][0]=0;
for(int j=1;j<=K;j++){
int b;
scanf("%d",&b);
rp+=b;
p[i][j]=rp;
}
}
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int k=0;k<=P;k++){
for(int j=0;j<=min(k,K);j++){
dp[i][k]=max(dp[i][k],dp[i-1][k-j]+p[i][j]);
}
}
printf("Case #%d: %d\n",++iCase,dp[n][P]);
}
return 0;
}
Workout 二分
Problem
Tambourine has prepared a fitness program so that she can become more fit! The program is made of N sessions. During the i-th session, Tambourine will exercise for Mi minutes. The number of minutes she exercises in each session are strictly increasing.
The difficulty of her fitness program is equal to the maximum difference in the number of minutes between any two consecutive training sessions.
To make her program less difficult, Tambourine has decided to add up to K additional training sessions to her fitness program. She can add these sessions anywhere in her fitness program, and exercise any positive integer number of minutes in each of them. After the additional training session are added, the number of minutes she exercises in each session must still be strictly increasing. What is the minimum difficulty possible?
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the two integers N and K. The second line contains N integers, the i-th of these is Mi, the number of minutes she will exercise in the i-th session.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimum difficulty possible after up to K additional training sessions are added.
这个题比较妙,需要二分这个最小的间隔,然后每个原来的 gap 中间需要加的数量是 ⌈ d i d b ⌉ − 1 \lceil \dfrac{d_i}{d_b}\rceil-1 ⌈dbdi⌉−1
#include<iostream>
#include<cstdio>
#define MAXN 100010
using namespace std;
int T,iCase,n,k,a[MAXN];
bool check(int d){
int res=0;
for(int i=2;i<=n;i++)
res+=(a[i]+d-1)/d-1;
return res<=k;
}
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
int md=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=n;i>=1;i--){
a[i]=a[i]-a[i-1];
if(a[i]>md)md=a[i];
}
int l=1,r=md;
while(l<r){
int mid=l+(r-l)/2;
if(check(mid))r=mid;
else l=mid+1;
}
printf("Case #%d: %d\n",++iCase,l);
}
return 0;
}
Bundling 字符串 Trie
Problem
Pip has N strings. Each string consists only of letters from A to Z. Pip would like to bundle their strings into groups of size K. Each string must belong to exactly one group.
The score of a group is equal to the length of the longest prefix shared by all the strings in that group. For example:
The group {RAINBOW, RANK, RANDOM, RANK} has a score of 2 (the longest prefix is ‘RA’).
The group {FIRE, FIREBALL, FIREFIGHTER} has a score of 4 (the longest prefix is ‘FIRE’).
The group {ALLOCATION, PLATE, WORKOUT, BUNDLING} has a score of 0 (the longest prefix is ‘’).
Please help Pip bundle their strings into groups of size K, such that the sum of scores of the groups is maximized.
Input
The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with a line containing the two integers N and K. Then, N lines follow, each containing one of Pip’s strings.
Output
For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the maximum sum of scores possible.
这个题也很好,把 n n n 个串进行分组,每组 k k k 个串,保证 k ∣ n k\mid n k∣n ,每组的分数是组内串的最长公共前缀的长度,求总的最大分数。
单独考虑一个组,假如这个组里的最长公共前缀 s s s 的长度是 L L L,那么认为 s s s 的每一个前缀 s [ 0 : i ] , i ∈ [ 1 , L ] s[0:i],i\in[1,L] s[0:i],i∈[1,L] 对分数贡献了 1 ,所以一个组的分数可以看成这个组内有多少个公共前缀。对于所有的串来说,一个前缀被共享的次数为 c n t cnt cnt ,那么它对总体的分数的贡献就是 ⌊ c n t k ⌋ \lfloor\dfrac{cnt}{k}\rfloor ⌊kcnt⌋,所以总体分数即为:
∑ i ⌊ c n t i k ⌋ \sum_{i}\lfloor\dfrac{cnt_i}{k}\rfloor i∑⌊kcnti⌋
其中 c n t i cnt_i cnti 表示前缀 p r e i pre_i prei 被所有串共享的次数。由此可以构造一个 Trie 来进行计算
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 2000010
#define MAXL 1000010
using namespace std;
int T,iCase,n,k,L,nxt[MAXN][26],e[MAXN],root;
char s[MAXL];
int newnode(){
for(int i=0;i<26;i++)
nxt[L][i]=-1;
e[L++]=0;
return L-1;
}
void insert(char *s){
int len=strlen(s);
int cur=root;
for(int i=0;i<len;i++){
if(nxt[cur][s[i]-'A']==-1)
nxt[cur][s[i]-'A']=newnode();
cur=nxt[cur][s[i]-'A'];
e[cur]++;
}
}
int main(){
#ifdef WINE
freopen("data.in","r",stdin);
#endif
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
L=0;root=newnode();
for(int i=0;i<n;i++){
scanf(" %s ",s);
insert(s);
}
int res=0;
for(int i=1;i<L;i++)res+=e[i]/k;
printf("Case #%d: %d\n",++iCase,res);
}
return 0;
}