2022“杭电杯”中国大学生算法设计超级联赛(5)补题

1010  Bragging Dice

题意

在神秘的东方,有一种古老的骰子游戏——“吹牛”。现在YahAHa和Peanut在玩吹牛。

游戏规则如下:

一局2人。每个玩家在杯子里都有n枚骰子。两个玩家都掷骰子一次。玩家轮流玩。YahAHa开始。在第一个回合中,YahAHa可以声称“2个杯子中有x(x≥1)个点为y(1≤y≤6)的骰子”。那么Peanut有2个选择。 1.挑战YahAHa。如果有人挑战,游戏就结束了。每个玩家打开杯子。如果杯子里真的有x个有y点的骰子,YahAHa赢,否则Peanut赢。 2.继续声称,但只能声称“有x1(x1>x)个骰子带有y1​(1≤y1≤6)点“或”有x2(x2=x)的骰子有y2(y2 > y)点”。Peanut索赔后,YahAHa继续选择挑战还是索赔。双方轮流进行,直到有人挑战,然后游戏结束。

为了让游戏更有趣,这里有一些特殊的规则。

1.如果没有人声称“杯子里有x个1点的骰子”,那么1点的骰子可以看作是骰子的任意点。 2.如果一个杯子里的所有骰子点数相同,则认为有一个额外的骰子点数相同。例如,如果有5个骰子,并且5个骰子都是6点,则认为有6个骰子是6点。 3.如果一个杯子里的每个骰子有不同的点数,则认为“杯子里有0个任意点数的骰子”。例如,如果有5个骰子,它们的点数是1点、2点、3点、4点和5点。人们认为“杯子里有0个1点的骰子”,“杯子里有0个2点的骰子”,...,“杯子里有5点0的骰子”。如果这三条规则有冲突,请先考虑第三条特殊规则。 YahAHa和Peanut不喜欢愚蠢的概率游戏,所以他们想玩这个游戏,同时知道2个杯子中每个骰子的点数。 给你他们掷出的所有骰子点数。YahAHa想弄清楚如果两人都最优地玩游戏谁会赢。

思路

当双方都扔出全部不同的点数时,两个杯中都相当于是空的,Y必输;其他情况下,只要Y说出两个杯中一共的最大个数的x个y,Y必胜。

代码

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
using namespace std;
int n;
int y[7];
int p[7];
signed main()
{
	IOS;
	
	int t;
	cin>>t;
	int i,j;
	int temp;
	bool biaoy;
	bool biaop;
	while(t--)
	{
		cin>>n;
		for(i=0;i<7;i++)
		{
			y[i]=0;
			p[i]=0;
		}
		biaoy=false;
		biaop=false;
		for(i=0;i<n;i++)
		{
			cin>>temp;
			y[temp]++;
		}
		for(i=0;i<n;i++)
		{
			cin>>temp;
			p[temp]++;
		}
		
		for(i=1;i<7;i++)
		{
			if(y[i]>1)
				biaoy=true;
			if(p[i]>1)
				biaop=true;
		}
		if(biaoy||biaop)
			cout<<"Win!\n";
		else
			cout<<"Just a game of chance.\n";
	} 
	
	
	
	
	return 0;
}

1012  Buy Figurines

题意

在“紫罗兰花园的色调”活动期间,作为职业女士Guuji的雇员,Sayu被指派购买其中一个雕像,那就是“雷电将军”。从1到n有n个人打算购买一个小雕像,商店有m个窗口,m个队列从1到m标识。第i个人的到达时间为ai以及花费的时间si去买一个小雕像(保证每个人的到达时间ai是不同的)。一个人到店,会选择排队人数最少的队伍。如果有多个人数最少的队列,他会选择标识符最小的队列。需要注意的是,如果有人同时离队,则该人会在所有人离队后选择队列。Sayu要等所有人都买完后再去买,求她购买的时间,及最后一个人买完的时间。

思路

采用STL。采用set存储排队信息,包括每队的序号和人数,自动按人数和序号进行排序。采用priority_queue存储人的信息,包括每个人的时间、序号、耗费的时间和状态,自动按人的到达时间进行排序。将所有人的状态一开始都设为1,轮到他时将状态改为0,将他的时间由到达时间改为结束时间,再将他送入队列中,直到下一次轮到他时,表明时间已经进行现在,他已经结束,此时可以将他从队伍中抹去,依次来代替时间。

代码

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <deque>
#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define int long long
using namespace std;
typedef pair<int,int> PII;
struct ren
{
	int sj;
	int id;
	int zt;
	int hf;
	bool operator<(const ren&t)const
	{
		if(sj==t.sj) 
			return zt>t.zt;
		return sj>t.sj;
	}
	ren(int a=0,int b=0,int c=0,int d=0):sj(a),id(b),zt(c),hf(d){}
};
priority_queue<ren>rren;

struct dui
{
	int num;
	int id;
	bool operator<(const dui&t)const
	{
		if(num==t.num) 
			return id<t.id;
		return num<t.num;
	}
	dui(int a=0,int b=0):num(a),id(b){}
}d[200005];
set<dui>ddui;

//PII data[200005];

int last[200005];//每一队的时间 
int wei[200005];//人在哪一队 

signed main()
{
	int t;
	cin>>t;
	int n,m;
	int i,j,k;
	dui duit;
	ren rent;
	int sj,id,zt,hf;
	int temp;
	int zong;
	while(t--)
	{
		ddui.clear();
		cin>>n>>m;
		int f,s;
		for(i=1;i<=n;i++)
		{
			cin>>f>>s;
			rent.sj=f;
			rent.id=i;
			rent.zt=1;
			rent.hf=s;
			rren.push(rent);
		}
		for(i=1;i<=m;i++)
		{
			last[i]=0;
			d[i].id=i;
			d[i].num=0;
			ddui.insert(d[i]);
		}
		while(rren.size())
		{
			rent=rren.top();
			rren.pop();
			
			sj=rent.sj;
			id=rent.id;
			zt=rent.zt;
			hf=rent.hf;
			if(zt==0)
			{
				temp=wei[id];
				ddui.erase(dui(d[temp].num,d[temp].id));
				ddui.insert(dui(--d[temp].num,d[temp].id));
			}
			else
			{
				duit=*ddui.begin();
				ddui.erase(duit);
				if(duit.num==0)
				{
					last[duit.id]=sj+hf;
				}
				else
				{
					last[duit.id]+=hf;
				}
				d[duit.id].num++;
				duit.num++;
				wei[id]=duit.id;
				ddui.insert(duit);
				rren.push(ren(last[duit.id],id,0,hf));
			}
			
		}
		
		zong=0;
		for(i=1;i<=m;i++) 
			zong=max(zong,last[i]);
		cout<<zong<<endl;
	}
	
	
	
	return 0;
}

1003  Slipper

题意

Gi是个淘气的孩子。他经常做一些奇怪的事情。因此,他的父亲决定和他玩一个游戏。 Gi的父亲是一个高级魔术师,他把Gi和Gi的拖鞋传送到一个迷宫里。为了简化这个问题,我们把迷宫看作一棵有n个节点的树,根节点为1。Gi最初在节点s,并且他的拖鞋在节点t。在树中,通过两个节点之间的任何边都要消耗w单位的功率。Gi也是个小魔术师!如果这两个节点之间的深度差等于k,他可以使用他的魔法传送到任何其他节点。也就是说,如果两个节点u、v满足|dep_u-dep_v|=k,然后Gi可以从u传送到v或者从v传送到u。但是每次当他使用魔法时,他需要消耗p单位的能量。请注意,他可以随时使用他的魔法。 需要用最小的能量单位拿走他的拖鞋。

思路

使用链式前向星建图,在建图时先将给出的边添加进去,再将深度差为k的边添加,不能直接将它们添加,数量过多,很容易超时,应创建虚点,使深度差为k的两个点中一个点到虚点的距离为0,另一个点到虚点的距离为q;再使用dijkstra找到起点到终点的花费最小的路线。

代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值