jzoj_2月1日D组

第一题(牛车)

题意:

    一些牛要开车上高速公路,第i头牛的车速为si,有m条高速公路,如果一条车道上前面有x头牛,那现在这头牛的速度就会降低d*x,我们现在要求最多能有多少头牛能上高速。

思路:

    先让他们的速度排序,因为最好是速度慢的先上高速比较好,然后从1到n头牛枚举,从1到m条车道枚举,如果这头牛可以上这条车道,我们就用一个数组统计这条车道上牛的数量,然后让ans+1。

代码:

#pragma G++ optimize (2)
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,d,l,s[50010],c[50010],ans,s1,t;
int max(int x,int y){return x>y?x:y;}
int main()
{
	scanf("%d%d%d%d",&n,&m,&d,&l);
	for (int i=1;i<=n;i++)
	  scanf("%d",&s[i]);
	sort(s+1,s+n+1);//快速排序
	for (int i=1;i<=n;i++)
	{   
	    for (int j=1;j<=m;j++)
		{
			t=s[i]-(c[j]*d);//c[j]为第j条车道上牛的数量
			s1=max(t,0);//题目中说了速度最小为0
            if (s1>=l) {c[j]++;ans++;break;} //如果速度满足条件就进行统计
		} 	
	}
	printf("%d",ans);
}

第二题(危险系数)

题意:

    按照给出的访问次序ai去探索岛屿,每个岛屿之间的危险系数是f[i][j],求我们按照这个访问次序去访问岛屿最少的危险系数。(我们的访问次序可以不连续,但要包含ai)。

思路:

    其实就是先求出两个岛屿间最少的危险系数,可以用Floyd求,然后再按照ai去累加最少的危险系数就好了。

代码:

#pragma GCC optimize (2)
#include<cstdio>
int n,m,a[10010],f[110][110],ans;
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	  scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
	  for (int j=1;j<=n;j++)
	  {
	       scanf("%d",&f[i][j]);//我这里没判断f[i][j]为0的情况,之前判断了就错了
	  }
	for (int k=1;k<=n;k++)
	  for (int i=1;i<=n;i++)
	    for (int j=1;j<=n;j++)
	      if (i!=k&&k!=j&&i!=j&&f[i][k]+f[k][j]<f[i][j]) f[i][j]=f[i][k]+f[k][j];//Floyd
    for (int i=1;i<=m-1;i++)
      ans+=f[a[i]][a[i+1]];//按照ai去累加
    printf("%d",ans);
}

第三题(前缀转后缀)

题意:

    给出一个只含有+-符号和数字的前缀表达式,求出它的后缀表达式。

思路:

    我们可以把前缀表达式变成树的形式,然后再用后序遍历输出后缀表达式,树的话就是符号每次读入,如果这个为符号,我们就读入它的孩子,后序遍历就是左右根的遍历。

代码:

#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char s[1111];
void read(int x)
{
	char c;
	cin>>c;
	if (c>'9'||c<'0')//如果是符号就读入它的孩子
	{
		s[x]=c;
		read(2*x);//左孩子
		read(2*x+1);//右孩子
	}else s[x]=c;//如果不是符号我们就直接存下来
}
void tree(int x)
{
	if (s[2*x]!='A') tree(2*x);//如果它有左孩子就遍历左的
	if (s[2*x+1]!='A') tree(2*x+1);//如果它有右孩子就遍历右的
	printf("%c ",s[x]);//左右根,左右遍历完了我们就可以输出根了
}
int main()
{
	freopen("j4.in","r",stdin);
	freopen("j4.out","w",stdout);
	for (int i=1;i<=1111;i++) s[i]='A';//A表示没有
	read(1);
	tree(1);
}

第四题(游戏)

题意:

    有两个人在玩游戏,有四种材料,每次他们都可以把其中的材料放进反应堆反应,有五种反应情况,每次反应都是会使材料化为乌有,他们玩n局游戏,每次给出四种材料的初值,当某个人选不了材料进行反应他就输了,他们都是用最好的方法去玩的。

思路:

    用记忆化搜索,每次的材料如果可以反应我们就从这里为起点搜,如果没有材料进行反应了我们就返回1,1是先手赢,因为1先拿,这时轮到2拿,没有材料了,所以就是1赢了,如果怎样都不能使2输,那就返回2赢,用f记录当前材料是谁能赢。

代码:

#pragma GCC optimize(2)
#include<cstdio>
int n,a,b,c,d,v[6][5],f[61][61][61][61];
int dfs(int A,int B,int C,int D)
{
	if (f[A][B][C][D]) return f[A][B][C][D];//这里是记录的地方,可以避免过多的搜索
	for (int i=1;i<=5;i++)
	{
		if (A>=v[i][1]&&B>=v[i][2]&&C>=v[i][3]&&D>=v[i][4])//v表示每次反应会消耗的对应材料
		{
			if (dfs(A-v[i][1],B-v[i][2],C-v[i][3],D-v[i][4])==2)
			{f[A][B][C][D]=1;
			return 1;}
		}
	}
	f[A][B][C][D]=2;
	return 2;
}
int main()
{
	freopen("j5.in","r",stdin);
	freopen("j5.out","w",stdout);
	scanf("%d",&n);
	v[1][1]=2;v[1][2]=1;v[1][4]=2;v[2][1]=1;v[2][2]=1;v[2][3]=1;v[2][4]=1;v[3][3]=2;v[3][4]=1;v[4][2]=3;v[5][1]=1;v[5][4]=1;
	for (int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&a,&b,&c,&d);
		if (dfs(a,b,c,d)==2) printf("Roland\n");//2是后手,Patrick是先手
		else printf("Patrick\n");
	}
}








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值