A - Choosing Teams
题意:问能组成多少支队伍,满足每支队伍三个人,并且能去k次比赛(上限5次)。
排序后,正常选。
#include<cstdio>
#include<algorithm>
using namespace std;
int a[2100];
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k)){
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
int t=0;
for(int i=2;i<n;i+=3){
if(a[i]+k<=5){
t++;
}
}
printf("%d\n",t);
}
}
B -Best Cow Line
题意:依次从头尾删字符,组成字典序最小的新串。
头尾选择字典序小的,相等就继续找。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
char a[2100];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){
cin>>a[i];
}
int l=0,r=n-1,t=0;
while(l<=r){
int flag=0;
for(int i=0;i+1<=r;i++){
if(a[l+i]<a[r-i]){
flag=1;
break;
}
else if(a[l+i]>a[r-i]){
flag=0;
break;
}
}
if(flag){
cout<<a[l++];
}
else cout<<a[r--];
t++;
if(t==80){
cout<<endl;
t=0;
}
}
}
}
C -ZCC Loves Codefires
题意:做每道题需要时间,而且时间会推移累加,罚时是时间乘以分数,问总罚时最少是。
贪心策略:优先选择罚分/罚时大的题做。注意long long
#include<bits/stdc++.h>
using namespace std;
struct node
{
long long t,v;
}a[100100];
bool cmp(node a,node b)
{
return a.v*b.t>b.v*a.t;
}
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){
scanf("%lld",&a[i].t);
}
for(int i=0;i<n;i++){
scanf("%lld",&a[i].v);
}
sort(a,a+n,cmp);
long long res=0,t=0;
for(int i=0;i<n;i++){
t+=a[i].t;
res+=t*a[i].v;
}
printf("%lld\n",res);
}
}
D - Doing Homework again
题意:每个作业有规定时间,和分数,没有按照规定时间内完成的作业,要被扣分数。
这题两个策略:先做分数大的作业,并且按最后规定时间做,不能就向前推移。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int visit[1010];
struct Node
{
int t,e;
}node[1010];
bool cmp(Node a,Node b)
{
return a.e>b.e||a.e==b.e&&a.t>b.t;
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
memset(visit,0,sizeof(visit));
int n;scanf("%d",&n);
for(int i=0;i<n;i++){ scanf("%d",&node[i].t);};
for(int i=0;i<n;i++) scanf("%d",&node[i].e);
sort(node,node+n,cmp);
int ans=0;
for(int i=0;i<n;i++)
{
int flag=0;
for(int j=node[i].t;j>0;j--)
{
if(visit[j]==0)
{
flag=1;
visit[j]=1;
break;
}
}
if(!flag) ans+=node[i].e;
}
printf("%d\n",ans);
}
}
E - Tian Ji -- The Horse Racing
题意:和历史上故事情景一模一样。
思路
一、当田忌最快的马比国王最快的马快时,用田忌最快的马赢国王最快的马。(赢的最有价值)
二、当田忌最快的马比国王最快的马慢时,用田忌最慢的马输给国王最快的马。(输的最有价值)
三、当田忌最快的马跟国王最快的马一样快时,如果田忌最慢的马比国王最慢的马还要快,直接比。如果不是,就让田忌最慢的马与国王最快的马比。(解释:这里有一种情况 是田忌最慢的马和国王最慢的马平时,不如让田忌最慢的马和国王最快的马比,两种情况结果都是输一次,但是这里牺牲田忌最慢的马区消耗 国王最快的马,更有价值。)
#include<cstdio>
#include<algorithm>
using namespace std;
int t[1010],k[1010];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++) scanf("%d",&t[i]);
for(int i=0;i<n;i++) scanf("%d",&k[i]);
sort(t,t+n,cmp);sort(k,k+n,cmp);
int t_fast=0,t_slow=n-1,k_fast=0,k_slow=n-1,win=0,lose=0;
while(t_fast<=t_slow)
{
if(t[t_fast]>k[k_fast])
{
win++;
t_fast++;
k_fast++;
}
else if(t[t_fast]<k[k_fast])
{
lose++;
k_fast++;
t_slow--;
}
else
{
if(t[t_slow]>k[k_slow])
{
win++;
t_slow--;
k_slow--;
}
else
{
if(t[t_slow]<k[k_fast])
lose++;
t_slow--;
k_fast++;
}
}
}
printf("%d\n",(win-lose)*200);
}
}
F - Proud Merchants
01背包的变形
题意:买东西,每个东西有三个特征值,p代表价格,q代表你手中钱必须不低于q才能买这个物品,v代表得到的价值。
mark:又是变种01背包,每做一个变种的,就是一种提高。。
这题因为涉及到q,所以不能直接就01背包了。因为如果一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m],再对第二个进行背包的时候,如果是普通的,应该会借用前面的dp[8],dp[7]之类的,但是现在这些值都是0,所以会导致结果出错。
于是要想到只有后面要用的值前面都可以得到,那么才不会出错。设A:p1,q1 B:p2,q2,如果先A后B,则至少需要p1+q2的容量,如果先B后A,至少需要p2+q1的容量,那么就是p1+q2 > p2+q1,变形之后就是q1-p1 < q2-p2。
#include<bits/stdc++.h>
using namespace std;
struct node
{
int p,q,v;
}a[555];
int cmp(node a,node b)
{
return a.q-a.p<b.q-b.p;
}
int dp[5555];
int main()
{
#ifdef yxj
freopen("F:\\in.txt","r",stdin);
#endif // yxj
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++) scanf("%d %d %d",&a[i].p,&a[i].q,&a[i].v);
sort(a,a+n,cmp);
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
for(int j=m;j>=a[i].q;j--)
dp[j]=max(dp[j],dp[j-a[i].p]+a[i].v);
printf("%d\n",dp[m]);
}
}
G - Bone Collector 标准的01背包
#include<cstring>
#include<climits>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<stack>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1010;
int dp[maxn],v[maxn],w[maxn];
int main()
{
int T;cin>>T;
while(T--){
memset(dp,0,sizeof(dp));
int n,W;cin>>n>>W;
for(int i=0;i<n;i++) cin>>v[i];
for(int i=0;i<n;i++) cin>>w[i];
for(int i=0;i<n;i++)
for(int j=W;j>=w[i];j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
cout<<dp[W]<<endl;
}
}
H - 数塔
#include<bits/stdc++.h>
using namespace std;
int dp[110][110],M[110][110];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;scanf("%d",&n);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
scanf("%d",&M[i][j]);
for(int i=1;i<=n;i++) dp[n][i]=M[n][i];
for(int i=n-1;i>0;i--)
for(int j=1;j<=i;j++)
dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+M[i][j];
printf("%d\n",dp[1][1]);
}
return 0;
}
I - Max Sum
最大子段和,需要记载坐标。
本题的状态方程:sum = sum > 0 ? sum+a:a;
*/
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
for(int step=1;step<=T;step++)
{
int n,s,e,k,sum=0,Max=-1000;
s=e=k=1;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
sum+=a;
if(sum>Max)
{
s=k;
e=i;
Max=sum;
}
if(sum<0)
{
sum=0;
k=i+1;
}
}
if(step!=1) printf("\n");
printf("Case %d:\n",step);
printf("%d %d %d\n",Max,s,e);
}
}
J - 母牛的故事
推出递推方程式:a[i]=a[i-1]+a[i-3];
<span style="font-size:14px;">#include<cstdio>
#include<algorithm>
using namespace std;
int a[100];
int main()
{
int n;
a[1]=1;
a[2]=2;
a[3]=3;
a[4]=4;
for(int i=5;i<=55;i++)
a[i]=a[i-1]+a[i-3];
while(~scanf("%d",&n)&&n)
{
printf("%d\n",a[n]);
}
return 0;
}</span>
K - Common Subsequence
标准最长公共子序列。
#include<bits/stdc++.h>
using namespace std;
char s1[1010],s2[1010];
int M[1010][1010];
int main()
{
while(~scanf("%s %s",s1,s2))
{
memset(M,0,sizeof(M));
int n=strlen(s1);
int m=strlen(s2);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s1[i-1]==s2[j-1])
M[i][j]=M[i-1][j-1]+1;
else
M[i][j]=max(M[i-1][j],M[i][j-1]);
printf("%d\n",M[n][m]);
}
return 0;
}
L - Super Jumping! Jumping! Jumping!
标准最长上升子序列
#include<bits/stdc++.h>
using namespace std;
int a[1010],dp[1010];
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
dp[i]=a[i];
}
for(int i=1;i<n;i++)
for(int j=0;j<i;j++)
if(a[i]>a[j])
dp[i]=max(dp[i],dp[j]+a[i]);
printf("%d\n",*max_element(dp,dp+n));
}
}
M - Milking cows
题意:0 牛向左看,1牛向右看,问怎么杀牛,让牛的总惊吓度最低(每有一头牛看到自己同胞被杀,惊吓度加一)
贪心策略:从左往右把向右看的牛杀掉,再从左向右,把所有向左看的牛杀掉(没有惊吓)。
#include<cstdio>
int main()
{
int n;
long long ans=0,sum=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
long long a;
scanf("%lld",&a);
if(a)
ans++;
else
sum+=ans;
}
printf("%lld\n",sum);
return 0;
}
N - 今年暑假不AC
活动时间安排问题。
贪心策略:按结束时间排序。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1000005;
int inf=0x3f3f3f3f;
LL mod=1e9+7;
struct Node
{
int s,e;
}node[110];
bool cmp(Node a,Node b)
{
return a.e==b.e? a.s<b.s:a.e<b.e;
}
int main()
{
int n;
while(cin>>n&&n)
{
for(int i=0;i<n;i++) cin>>node[i].s>>node[i].e;
sort(node,node+n,cmp);
int ans=0,t=0;
for(int i=0;i<n;i++)
{
if(t<=node[i].s)
{
t=node[i].e;
ans++;
}
}
cout<<ans<<endl;
}
}