首页 > 代码库 > [大山中学晚练] 2016.9.28

[大山中学晚练] 2016.9.28

这次晚练十分sb 有点浪费时间 全是dp题

先说过程 3分钟草了第一题之后感觉好像有点水 然后翻了翻题目 看了看第一第四题两颗星 其他三颗星 然后一下子第二题题目太长就兴起草第三题 打了四十五分钟然后草第二题 然后就没了要收卷(第二题还没调完 给多我五分钟就A了) 整体用了一个半小时吧(马力有点弱..)

 

 

技术分享

三维dp 你也可以变成N和K的dp只是麻烦一点 这题不会可以退役

 

技术分享
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#define Maxn 1010using namespace std;int F[Maxn][40][2]; int T[Maxn];int main(){  freopen("bcatch.in","r",stdin);  freopen("bcatch.out","w",stdout);  int N,K; scanf("%d%d",&N,&K); for(int i=1;i<=N;i++) scanf("%d",&T[i]);  for(int i=1;i<=N;i++)  {    for(int j=0;j<=K;j++)    {      F[i][j][0]=max(F[i][j][0],max(F[i-1][j][0],F[i-1][j-1][1])+(T[i]==1));      F[i][j][1]=max(F[i][j][1],max(F[i-1][j][1],F[i-1][j-1][0])+(T[i]==2));    }  }  int maxx=0;  for(int i=0;i<=K;i++) for(int j=0;j<=1;j++) maxx=max(maxx,F[N][i][j]);  return printf("%d\n",maxx),0;}/*72112211*/
View Code

 

技术分享

第二题题目很烦 条件很多 我们发现斜坡是越短越好 然后用时间和能力值dp一下随便草就好了

技术分享
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>using namespace std;struct Course{  int m,l,a;}C[110];bool Cmp(const Course &x,const Course &y){return x.m<y.m;}struct XP{  int c,d;}X[100010];int T,S,N;int F[10010][110];int L[110];int main(){  freopen("ski.in","r",stdin);  freopen("ski.out","w",stdout);  scanf("%d%d%d",&T,&S,&N);  for(int i=1;i<=S;i++) scanf("%d%d%d",&C[i].m,&C[i].l,&C[i].a);  sort(C+1,C+S+1,Cmp);  for(int i=1;i<=N;i++) scanf("%d%d",&X[i].c,&X[i].d);    for(int i=0;i<=100;i++) L[i]=10000;  for(int i=1;i<=N;i++) L[X[i].c]=min(L[X[i].c],X[i].d);  for(int i=1;i<=100;i++) L[i]=min(L[i],L[i-1]);    for(int i=0;i<=T;i++) for(int j=0;j<=100;j++) F[i][j]=-1;  F[0][1]=0; int l=1; int r=1;  for(int i=0;i<=T;i++)  {    while(C[r].m==i) r++;    for(int j=0;j<=100;j++)    {      if(F[i][j]!=-1)      {        F[i+1][j]=max(F[i+1][j],F[i][j]);        if(i+L[j]<=T) F[i+L[j]][j]=max(F[i+L[j]][j],F[i][j]+1);        for(int k=l;k<r;k++) if(i+C[k].l<=T) F[i+C[k].l][C[k].a]=max(F[i+C[k].l][C[k].a],F[i][j]);      }    }    l=r;  }  int maxx=0;  for(int i=1;i<=T;i++) for(int j=1;j<=100;j++) maxx=max(maxx,F[i][j]);  return printf("%d\n",maxx),0;}/*10 1 23 2 54 11 3*/
View Code

 

技术分享

第三题也想了一会儿 我们发现有一些状态我们是一定到不了的 就好比

7 3

8 5

其实8的时候最多为4 就改一下 还有一种

7 3

8 1

那么你7是要改成2的

先从后面扫一遍 然后前面再扫一遍到后面(先后顺序不知道可不可以换 应该可以吧 考场上没多想)

剩下的话都是可以到的 然后每次都到这个速度就是最优的因为你如果合法 但是又小于这个速度就是最差的 那么的话每两个点之间你就把它们先升到一个高度然后再往上飞最长的一段再下来

最后还要判断一下到终点 (就这样没了两个点)

技术分享
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cstdlib>#define Maxn 100010using namespace std;bool Cmp(const pair<int,int> &x,const pair<int,int> &y){if(x.first!=y.first) return x.first<y.first; return x.second>y.second;}int L,M; pair<int,int>pr[Maxn];int F[Maxn];int main(){  freopen("bobsled.in","r",stdin);  freopen("bobsled.out","w",stdout);  scanf("%d%d",&L,&M); for(int i=1;i<=M;i++) scanf("%d%d",&pr[i].first,&pr[i].second);  sort(pr+1,pr+M+1,Cmp); memset(F,63,sizeof(F)); F[0]=1;  for(int i=1;i<=M;i++) F[i]=min(F[i],pr[i].second);  for(int i=M;i>=1;i--)  {    if(pr[i].first!=pr[i+1].first)    {      F[i]=min(F[i],F[i]+(F[i+1]-F[i])+(pr[i+1].first-pr[i].first));    }            else F[i]=F[i+1];  } int l;  for(int i=1;i<=M;i=l+1)  {    l=i; while(pr[l].first==pr[l+1].first) l++;    if(pr[l].first!=pr[i-1].first)    {      F[l]=min(F[l],F[l]+((F[i-1]-F[l])+(pr[l].first-pr[i-1].first)));    }    for(int j=i;j<=l;j++) F[j]=F[l];  }    int ans=0;  for(int i=1;i<=M;i++) ans=max(ans,max(F[i],F[i-1])+(pr[i].first-pr[i-1].first-abs(F[i]-F[i-1]))/2);  ans=max(ans,F[M]+(L-pr[M].first));  return printf("%d\n",ans),0;}/*14 37 311 113 8*/
View Code

 

技术分享

看看范围 好像直接背包会爆 很明显这道题给出来的做法一定是NM 然后想想背包可不可以换种方式

看到都是M的倍数 也就是说 M以上的都可以变成小于M咯 其它也要保留一下 然后F[N][i]表示现在放到第I个物品 然后M的倍数+i 然后再用一个数组辅助转移搞一下就好了 差不多绕圈的dp

技术分享
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#define Maxn 2010using namespace std;const int Mod=1e8;int N,M; int A[Maxn]; int F[Maxn]; bool bo[Maxn]; int G[Maxn];int main(){  freopen("fristeam.in","r",stdin);  freopen("fristeam.out","w",stdout);  scanf("%d%d",&N,&M);  for(int i=1;i<=N;i++) scanf("%d",&A[i]);  memset(F,0,sizeof(F)); F[0]=1; memset(G,0,sizeof(G)); memset(bo,0,sizeof(bo)); bo[0]=1;  for(int i=1;i<=N;i++)  {    for(int j=0;j<M;j++) G[j]=0;    for(int j=0;j<M;j++)      if(bo[j]) G[(j+A[i])%M]=(G[(j+A[i])%M]+F[j])%Mod,bo[(j+A[i])%M]=1;    for(int j=0;j<M;j++)      if(bo[j]) F[j]=(F[j]+G[j])%Mod;  }  return printf("%d\n",F[0]-1),0;}/*4 51282*/
View Code

 

[大山中学晚练] 2016.9.28