zoukankan      html  css  js  c++  java
  • Chapter 32: 动态规划小测总结 (USACO的???

    前言+总结

    四道题两个小时,都是2~3星的DP。最终300分,诶DP弱到不行的我也算是这样了吧orz。

    花了快一个小时搞第一题(发现自己好搞笑啊,一直觉得自己的方程很简单会不会漏了什么一直在看= =);然后跳了第二题去打第三题,用了大概十五分钟,感觉这个细节蛮多的,打得我好虚啊;最后一题也大概打了十五分钟吧,挺水的,,一开始还想弄个一维的算了,发现不行= =,就直接改成滚动了√然后重新搞了几下这三题,静态查错了一下,好像没什么不对的,就剩十分钟了,ORZ,没时间搞第二题了QwQ【还想拼拼手速十分钟第二题来着完了发现方法不对啊  果然都要先思考啊。

    怎么说,看完题有个大概思路还是很重要的,有时候就不要想那么多那些有的没的= =简直浪费时间。

    插曲:

    刚打完第一题的我,发现hyc一脸无奈(???)的看着我,我就冲她摇摇头表示我不会做;蒟蒻打完第三题的时候,发现她又看着我,我表示疑惑,于是她说:我刚刚打了1、4题的对拍,发现我第1题sabi了。。。我:???你打完了?!!! hyc:是啊还打了两个对拍。我:ORZORZORZ...too naive的我


    题目+题解

    第一题


    因为只有两个苹果树,且知道了起始位置,那么当确定了移动了多少次的时候就能确定此时处在那一棵树下。

    于是设f[i][j],表示i时刻时已经移动了j次。

    转移方程为:f[i][j]=max(f[i-1][j],f[i-1][j-1])+(该状态下有没有苹果接)


    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long LL;
    using namespace std;
    #define N 1100
    #define M 50
    
    int f[N][M],a[N];
    int mymin(int x,int y){return (x<y)?x:y;}
    int mymax(int x,int y){return (x>y)?x:y;}
    int main()
    {
    	//freopen("bcatch.in","r",stdin);
    	//freopen("bcatch.out","w",stdout);
    	int n,k,i,j,ans=0;
    	memset(f,0,sizeof(f));
    	scanf("%d%d",&n,&k);
    	for (i=1;i<=n;i++) scanf("%d",&a[i]);
    	for (i=1;i<=n;i++)
    	{
    		f[i][0]=f[i-1][0]+(a[i]==1);
    		for (j=1;j<=k;j++)
    		{
    			if (j>i) break;
    			f[i][j]=mymax(f[i-1][j],f[i-1][j-1]);
    		 	if (a[i]%2==(j+1)%2) f[i][j]+=1;//判断此状态有没有苹果接
    			ans=mymax(ans,f[i][j]);
    		}
    	}printf("%d
    ",mymax(ans,f[n][0]));//本来没有把一直不动的更新到ans里= =数据弱啊
    	return 0;
    }

    ============================================

    第二题


    我跳了。。因为两种东西感觉好麻烦= =

    好吧说解法。当你发现能力值只有100的时候,就很容易想到把 什么时候都能去滑 的那个给预处理了。

    设bs[i],表示当能力值为i时,能去滑的滑雪中一次所耗费的最小时间。

    f[i],就表示一定上第i门课时能滑的最大次数。


    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define T 100100
    
    struct node
    {
    	int m,l,a;
    }cl[T];int bs[110];
    int f[T];
    bool cmp(node x,node y)
    {
    	if (x.m!=y.m) return x.m<y.m;
    	if (x.a!=y.a) return x.a-y.a;
    	return x.l<y.l;
    }
    int mymin(int x,int y){return (x<y)?x:y;}
    int mymax(int x,int y){return (x>y)?x:y;}
    int main()
    {
    	//freopen("ski.in","r",stdin);
    	//freopen("ski.out","w",stdout);
    	int t,s,n,i,j,x,y,ans=0;
    	scanf("%d%d%d",&t,&s,&n);
    	for (i=1;i<=s;i++)
    	 scanf("%d%d%d",&cl[i].m,&cl[i].l,&cl[i].a);
    	memset(bs,63,sizeof(bs));
    	memset(f,0,sizeof(f));
    	for (i=1;i<=n;i++)
    	{
    		scanf("%d%d",&x,&y);
    		bs[x]=mymin(bs[x],y);
    	}//预处理bs[]
    	for (i=2;i<=100;i++) bs[i]=mymin(bs[i-1],bs[i]);
    	sort(cl+1,cl+1+s,cmp);//对课程排下序
    	cl[0].m=cl[0].l;cl[0].a=1;
    	for (i=1;i<=s;i++)
    	  if (cl[i].m+cl[i].l<=t)
    	  //看看上完这门课程是否还在限制内
    	  {
    		  for (j=0;j<i;j++)//枚举上一次上的课是那个
    		  {
    			  int sc=(cl[i].m-(cl[j].m+cl[j].l))/bs[cl[j].a];
    			  //sc就是上次上完课后到这次上课前去滑雪能滑的(最大)次数
    			  f[i]=mymax(f[i],f[j]+sc);
    		  }
    		  ans=mymax(ans,f[i]);
    		  ans=mymax(ans,f[i]+(t-cl[i].m-cl[i].l)/bs[cl[i].a]);
    	  }
    	ans=mymax(ans,t/bs[1]);//这是不上课的
    	printf("%d
    ",ans);
    	return 0;
    }
    

    ===========================================

    第三题


    这道题,额贪心水了过去。因为过程中发现自己漏了一些细节,打得好虚!还好都有考虑到。

    先按位置排序,去重(某点多个限制就去最小)。[然而似乎数据并不需要我做这些- -

    我是直接贪在两个限制间我能到的最大速度嘛,所以首先要保证,当我刚好处于前面位置的限制速度时,我一定能保证后面不会超速。所以就从后往前扫一遍,用后面的限速来限制前面的。以此来保证肯定合法。

    处理完这些,就直接扫一遍啊,两个限制点间的速度肯定呈 先递增后递减 或 单调递增/减,而这些取决于这两个点限制速度的大小关系。【不造怎么说。。看代码吧orzorzorz


    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    #define maxn 101000
    
    LL mymin(LL x,LL y){return (x<y)?x:y;}
    LL mymax(LL x,LL y){return (x>y)?x:y;}
    struct node {LL w,v;}a[maxn];
    bool cmp(node x,node y)
    {
    	if (x.w!=y.w) return x.w<y.w;
    	return x.v<y.v;
    }
    int main()
    {
    	//freopen("bobsled.in","r",stdin);
    	//freopen("bobsled.out","w",stdout);
    	LL l,n,i,ln,ans,v,w;
    	scanf("%I64d%I64d",&l,&n);
    	for (i=1;i<=n;i++)
    	 scanf("%I64d%I64d",&a[i].w,&a[i].v);
    	sort(a+1,a+1+n,cmp);ln=0;
    	for (i=1;i<=n;i++)
    	 if (a[i].w!=a[i-1].w) a[++ln]=a[i];//去重
    	n=ln;ans=0;v=1;w=0;
    	for (i=n-1;i>=1;i--)//保证合法性
    	 a[i].v=mymin(a[i].v,a[i+1].w-a[i].w+a[i+1].v);
    	for (i=1;i<=n;i++)
    	{
    		if (a[i].v>=v)
    		{
    			if (a[i].v-v<=a[i].w-w)//速度曲线呈先递增后递减
    			{
    				ans=mymax(ans,a[i].v+((a[i].w-w)-(a[i].v-v))/2);
    				v=a[i].v;
    			}else {ans=mymax(ans,v+(a[i].w-w));v+=(a[i].w-w);}
    			//单调递增 注意,此时速度不一定能到达限制速度所以不能直接v=a[i].v
    		}else
    		{
    			ans=mymax(ans,v+((a[i].w-w)-(v-a[i].v))/2);//单调递减
    			v=a[i].v;
    		}w=a[i].w;
    	}ans=mymax(ans,v+(l-w));//不要忘了能一直加速至终点!
    	printf("%I64d
    ",ans);
    	return 0;
    }

    =============================================

    第四题


    这个很好想啊,f[i]就表示余数为i的有多少个。

    数据范围明显让你O(nm)啊,就这样搞搞就好了。

    不要作死想一维过了,还是好好打二维吧


    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    typedef long long LL;
    using namespace std;
    #define maxn 2100
    #define mod 100000000
    
    LL f[2][maxn];int a[maxn];
    int main()
    {
    	//freopen("fristeam.in","r",stdin);
    	//freopen("fristeam.out","w",stdout);
    	int n,m,i,j,t;
    	scanf("%d%d",&n,&m);
    	for (i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		a[i]=a[i]%m;
    	}t=1;
    	memset(f,0,sizeof(f));
    	for (i=1;i<=n;i++)
    	{
    		for (j=m-1;j>=0;j--)
    	 	{
    			f[t][(j+a[i])%m]+=f[1-t][j];
    			f[t][(j+a[i])%m]=f[t][(j+a[i])%m]%mod;
    	 	}f[t][a[i]]++;f[t][a[i]]%=mod;
    		for (j=0;j<=m-1;j++)
    		{
    			f[t][j]=(f[t][j]+f[1-t][j])%mod;
    			f[1-t][j]=0;
    		}t=1-t;
    	 }
    	printf("%I64d
    ",f[1-t][0]);
    	return 0;
    }
    


  • 相关阅读:
    eclipse经常卡死、反应慢、内存溢出的解决方案
    PAC4J 初探
    suse11离线安装nginx
    linux修改乱码的文件名
    CentOS修改服务器系统时间
    Unable to open nested entry '********.jar' 问题解决
    openssl req(生成证书请求和自建CA)
    CRT证书转JKS证书
    如何创建一个自签名的SSL证书(X509)
    Redis分布式锁的深度剖析
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527860.html
Copyright © 2011-2022 走看看