zoukankan      html  css  js  c++  java
  • 【NOIP2011模拟11.1】钓鱼

    钓鱼

    题目

    Description

    在这里插入图片描述
    我们把钓鱼的过程放在坐标系里来考虑。图中蓝色的点为船,初始时它的坐标记为(Ax,y)。河深为y,河宽为x。某个时刻会从左边界或右边界游出来一条鱼(左边的往右边游,右边的往左边游),即鱼游出来时的横坐标为0或x,这条鱼每秒会游D个单位长度,鱼的长度为L。初始时刻为0,对于每个时刻x,船可以选择花费1s向左或向右移动最多Q个单位长度,或者选择在当前位置进行钓鱼,钓鱼的动作是瞬间的,且发生在时刻x,鱼还来不及移动就被钓上了。如果选择钓鱼,那么在时刻x就不能动。{x+1时刻可以选择移动}设当前位置为z,将鱼看成一条线段,当线段与直线x=z相交时就认为鱼上钩了,所以一次钓鱼动作可能会钓多条鱼。
    聪明的你告诉钓鱼者,在T时刻前最多能钓多少鱼?

    Input

    输入:
    第一行:T
    第二行:Maxx,Maxy,表示河宽和河深
    第三行:两个数Ax,Q
    第四行:N,表示有N条鱼
    接下来N行描述每条鱼:每行共五个数,x,y,D,L,time
    x表示鱼头的初始位置,保证为0或maxx,y表示鱼头的初始深度,time表示鱼出现的时刻(所有的数都为整数)

    Output

    输出:
    只有一行:ans,表示最多的钓鱼数

    Sample Input

    3
    4 5
    4 1
    3
    0 1 3 1 0
    4 2 2 1 0
    0 3 3 1 2

    Sample Output

    3

    Data Constraint

    100%的数据满足
    1<=T,time<=10
    1<=Ax,Ay,Q,x,y,D,L<=10
    1<=N<=14

    30%的数据满足
    1<=N<=5

    总结

    考试的时候想到了状压DP,但没有进一步去想
    其实这题的转移方程十分简单,也容易想到,但是就是放弃了
    所以说有想法就可以继续钻研下去

    题解

    首先题目要求的是T时刻前,其实是包括T的
    所以说总共会进行T+1次操作
    看到N很小,考虑状压
    (f[i][j][s])表示现在是(i)时刻,(j)位置,鱼的情况是(s)(被钓了是1,没有是0)的最大鱼数
    转移分两种(以下方程都需要和原来的取(max)

    1. 移动。那么(f[i+1][j-q…j+q][s]=f[i][j][s])
    2. 钓鱼。(f[i+1][j][s1]=f[i][j][s]+sum)
      (s1)表示钓鱼后的情况,(sum)表示钓上来的数量

    对于判断是否钓上来,可以预处理每条鱼在每一分钟的位置,然后循环扫一遍
    初始化(f[0][Ax][0]=0),其余的是-1

    Code

    #include<bits/stdc++.h>
    using namespace std;
    int t,mx,my,pos,q,n,sum,s1,ans,st[15],de[15],v[15],l[15],_time[15],fh[15],head[15][15],tail[15][15],f[15][15][33000];
    int read()
    {
    	int res=0;char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while (ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch-'0'),ch=getchar();
    	return res;	
    }
    int main()
    {
    	t=read();mx=read();my=read();pos=read();q=read();n=read();
    	for (int i=1;i<=n;++i)
    	{
    		st[i]=read();de[i]=read();v[i]=read();l[i]=read();_time[i]=read();
    		if (st[i]==0) fh[i]=1;
    		else fh[i]=-1;
    	}
    	for (int i=1;i<=n;++i)
    		for (int j=0;j<=t;++j)
    		{
    			if (_time[i]==j)
    			{
    				head[i][j]=st[i];
    				tail[i][j]=st[i]-fh[i]*l[i];
    			}
    			if (_time[i]<j)
    			{
    				head[i][j]=head[i][j-1]+fh[i]*v[i];
    				tail[i][j]=tail[i][j-1]+fh[i]*v[i];
    			}
    		}
    	memset(f,-1,sizeof(f));
    	f[0][pos][0]=0;
    	for (int i=0;i<=t;++i)
    		for (int j=0;j<=mx;++j)
    			for (int s=0;s<(1<<n);++s)
    			{
    				if (f[i][j][s]==-1) continue;
    				for (int k=max(0,j-q);k<=min(j+q,mx);++k)
    					f[i+1][k][s]=max(f[i+1][k][s],f[i][j][s]);
    				sum=0;
    				s1=s;
    				for (int k=1;k<=n;++k)
    					if (_time[k]<=i&&!(s1&(1<<(k-1))))
    						if ((head[k][i]>=j&&tail[k][i]<=j)||(head[k][i]<=j&&tail[k][i]>=j)) ++sum,s1|=(1<<(k-1));
    				f[i+1][j][s1]=max(f[i+1][j][s1],f[i][j][s]+sum);
    			}
    	ans=-1;
    	for (int k=0;k<=t+1;++k)
    		for (int i=0;i<=mx;++i)
    			for (int j=0;j<(1<<n);++j)
    				ans=max(ans,f[k][i][j]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    浅谈隔板法
    最短路spaf及dijkstra模板
    P1219 最优贸易
    P1211 街道赛跑
    图结构模板
    P1218 过路费
    使用Asp.net Identity 创建用户 、登录代码
    asp.net identity 介绍
    响应式图像
    glyphicon 图标的使用
  • 原文地址:https://www.cnblogs.com/Livingston/p/13772513.html
Copyright © 2011-2022 走看看