模拟3

WEEK6 模拟题

题目大意

给出两个数A,B,表示牌的大小为:0到A-1, 花色为:0到B-1,再给出a1,b1,a2,b2,表示:(a1,b1),(a2,b2)两张牌,现从其余牌中再拿出3张牌,现要求预测以下9种情况,对应的5张牌的组合个数,按照低序号优先原则记数。

同花顺: 同时满足规则 2 和规则 3.
顺子 : 5张牌的大小形如 x, x + 1, x + 2, x + 3, x + 4
同花 : 5张牌都是相同花色的.
炸弹 : 5张牌其中有4张牌的大小相等.
三带二 : 5张牌其中有3张牌的大小相等,且另外2张牌的大小也相等.
两对: 5张牌其中有2张牌的大小相等,且另外3张牌中2张牌的大小相等.
三条: 5张牌其中有3张牌的大小相等.
一对: 5张牌其中有2张牌的大小相等.
要不起: 这手牌不满足上述的牌型中任意一个.

思路

这个题最好的思路就是直接枚举所有的组合情况,由于数据量很小,最坏情况就是 O ( 25 ∗ 25 ∗ 25 ∗ 4 ∗ 4 ∗ 4 ) O(25*25*25*4*4*4) O(252525444),也就是1e6的复杂度,所以直接DFS枚举就可以,只需要注意3点:

  1. 同一组内不能有牌的花色和大小完全相同的牌
  2. 低序号优先,同花顺不能再属于顺子或同花。
  3. 最后要除掉顺序,也就是所有结果除 A 3 3 = 6 A^3_3=6 A33=6
代码
#include<bits/stdc++.h>
using namespace std;
int ans[10];
int num[10];
int color[10];
int cnt=0;
int a=0,b=0;
int a1=0,a2=0,b1=0,b2=0;
bool flag=0;
void check()
{
	bool isseq=0; //
	bool samech=0;
	int num2[10];
	int col2[10];
	for(int k=1;k<=5;k++){
		num2[k]=num[k];
		col2[k]=color[k];
	}
	sort(num2+1,num2+6);
	for(int i=1;i<5;i++){
		if(num2[i]+1!=num2[i+1]){
			isseq=0;
			break;
		}  
		else isseq=1;
	}
	
	sort(col2+1,col2+6);
	if(col2[1]==col2[5]) samech=1;	

	if(isseq ==1 && samech==1) ans[0]++;
	else if(isseq==1) ans[1]++;
	else if(samech==1) {
	   ans[2]++; // if is samechar , can't be else
//	   for(int j=1;j<=5;j++) cout<<num2[j]<<" : "<<col2[j]<<endl;
//	   cout<<endl;
    }  
	//bomb
	else if(num2[1]==num2[4]&&num2[4]!=num2[5]) ans[3]++;
	else if(num2[1]!=num2[2]&&num2[2]==num2[5]) ans[3]++;
	//3 +2
	else if(num2[1]==num2[3]&&num2[4]==num2[5]) ans[4]++;
	else if(num2[1]==num2[2]&&num2[3]==num2[5]) ans[4]++;
	// 2 pair
	else if(num2[1]==num2[2] && num2[3] == num2[4]) ans[5]++;
	else if(num2[1]==num2[2] && num2[4]==num2[5])  ans[5]++;
	else if(num2[2]==num2[3]&&num2[4]==num2[5]) ans[5]++;
	//3tiao
	else if(num2[1]==num2[3]||num2[2]==num2[4]||num2[3]==num2[5]) ans[6]++;
	//1 pair
	else if(num2[1]==num2[2] || num2[2]==num2[3] || num2[3]==num2[4] ||num2[4]==num2[5]) 
	ans[7]++;
	//nothing
	else ans[8]++;
}

void solve(int i)
{
	if(i==6)
	{
        check(); //计算
	    return;	 	
	}
	else if(i<=5)
	{
	 for(int j=0;j<a;j++)
	   {
	 	 for(int k=0;k<b;k++)
		  {
				num[i]=j;
				color[i]=k;
				for(int s =1;s<i;s++)
				{ //判断刚加入的牌,是否和前边重复
					if(num[i]==num[s] && color[i]==color[s]) 
					{
						flag=1;
						break;
					}
				}
				if(flag==0) solve(i+1);
				else flag=0;
		 }
	 	
	   }	
	
	}

}
int main()
{
  	scanf("%d%d",&a,&b);
	scanf("%d%d%d%d",&a1,&b1,&a2,&b2);	
	memset(num,0,sizeof num);
	memset(color,0,sizeof color);
	memset(ans,0,sizeof ans);
	num[1]=a1,num[2]=a2;
	color[1]=b1,color[2]=b2;
	solve(3);
	
	for(int i=0;i<9;i++)
	{
		if(i==0) printf("%d",ans[0]/6); //除顺序
		else printf(" %d",ans[i]/6);
	}
	cout<<endl;
	return 0;	
}
注意点

这种模拟题不是数学题,这个题数据量很小,明显直接DFS就可以解决,不需要根据排列组合算答案,那就不是模拟题了。这里附一下大半天排列组合的计算结果(这也是为什么考试的时候没做完的原因,一定要注意这一点,思路要找准.)

#include<bits/stdc++.h>
using namespace std;
int ans[10];
int temp[10];
int a=0,b=0;
int a1=0,a2=0,b1=0,b2=0;
//memset(ans,0,sizeof ans);
int kind=0;
int samech=0;
bool isseq() //顺子 
{
	if(abs(a1-a2)<5&&a1!=a2)
	{
		for(int i=0;i<a;i++)
			for(int j=0;j<a;j++)
				for(int k=0;k<a;k++)
				   {
				   	    temp[0]=a1;
		                temp[1]=a2;
						temp[2]=i,temp[3]=j,temp[4]=k;
						if(a1!=a2&&a2!=i&&i!=j&&j!=k)
						{
						    sort(temp,temp+5);
						    if(temp[0]+1==temp[1]&&temp[1]+1==temp[2]&&
						    temp[2]+1==temp[3]&&temp[3]+1==temp[4])   kind++;
						}		
				   }		
		kind/=6;
	}
	if(kind>0) return 1;
	else return 0;
}
bool samechar()  
{
	if(b1==b2) 
    {
		samech=(a-2)*(a-3)*(a-4)/6; //同花 
		return 1;
	}
	return 0;
}
int main()
{
//	freopen("in.txt","r",stdin);
	scanf("%d%d",&a,&b);
	scanf("%d%d%d%d",&a1,&b1,&a2,&b2);
	if(isseq()&&samechar())
	{
		ans[0]=kind;    //同花顺 
	} 
	if(isseq()) ans[1]=kind*(b*b*b)-ans[0];
	if(samechar()) ans[2]=samech-ans[0];
	if(b==4)
	 { //炸弹 
		if(a1!=a2) ans[3]=2;
		else if(a1==a2) ans[3]=(a-1)*b; 
	} 
    if(b>=3) //3带2 
	{
	    if(a1!=a2) ans[4]=(b-1)*(b-2)*(b-1);
		else if(a1==a2)  ans[4]=(b-2)*(a-1)*(b-1)*b/2+(b)*(b-1)*(b-2)*(a-1)/6;
	}
   if(b>=2) //两对 
	{
		if(a1!=a2)  ans[5]=2*b*(b-1)*(b-1)*(a-2);
		else if(a1==a2) ans[5]=(a-1)*b*(b-1)*(a-2)*b/2;	
	}
    if(b>=3) //三条 
	{
		if(a1==a2) ans[6]=b*b*(b-2)*(a-1)*(a-2)/2; 
		else if(a1!=a2) {
			ans[6]=b*(b-1)*(b-2)*(a-2)+(a-2)*b*(b-1)*(b-2)/6;
//			cout<<b*(b-1)*(b-2)*(a-2)<<" "<<(a-2)*b*(b-1)*(b-2)/6<<endl;
	
		}
	}	
	if(b>=2) //一对 
	{
		if(a1==a2) ans[7]=(a-1)*(a-2)*(a-3)/6*b*b*b;
		else if(a1!=a2) ans[7]=(b-1)*b*b*(a-2)*(a-3)/2+(b-1)*b*b*(a-2)*(a-3);
	}
    if(a1!=a2)
	{
		if(b1!=b2) ans[8]=b*b*b*(a-2)*(a-3)*(a-4)/6-ans[1]; //去顺子 
		else if(b1==b2) { ans[8]=(b*b*b-1)*(a-2)*(a-3)*(a-4)/6-ans[1];
		//不是同花色的不一样的序列 减顺子+同花顺 
		} 
	} 
	
	for(int i=0;i<9;i++)
	{
		if(i==0) printf("%d",ans[0]);
		else printf(" %d",ans[i]);
	}
	cout<<endl;
	return 0;
}

月模拟题:ASCII码画图

题目大意:

定义两种操作:

  1. 画线:0 x1,y1,x2, y2 ;给出两个端点的坐标,画一条连接这两个端点的线段。简便起见题目保证要画的每条线段都是水平或者竖直的。水平线段用字符 - 来画,竖直线段用字符 | 来画。如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。
  2. 填充:1,x1,y1,x2,y2 ,C ; 给出填充的起始位置坐标和需要填充的字符,从起始位置开始,用该字符填充相邻位置,直到遇到画布边缘或已经画好的线段。注意这里的相邻位置只需要考虑上下左右 4 个方向。填充的字符为大写字母
    所有的点初始都是‘.’,根据给出的命令,画出对应的ASCII形成的图。

输入:

16 13 9
0 3 1 12 1
0 12 1 12 3
0 12 3 6 3
0 6 3 6 9
0 6 9 12 9
0 12 9 12 11
0 12 11 3 11
0 3 11 3 1
1 4 2 C

效果:

................
...+--------+...
...|CCCCCCCC|...
...|CC+-----+...
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC+-----+...
...|CCCCCCCC|...
...+--------+...
................

思路

这个题只需在初始化好画布之后,根据要求画线或填充相应的字母即可,只需注意:

  1. 画线操作交叉点是’+’,特别注意的是,无论’-‘或’|’,若下一个填充位置是‘+’,则应该跳过,保持’+'不变。
  2. 填充的时候,是一个BFS的操作,以画布,’-’, ‘+’, ‘|’ 为界限,其余位置只要不等于当前待填充字符,都可以填充。
代码

由于题目中的坐标和二位数组中的坐标是不一样的,(二者相当于关于题目坐标系的X轴对称),所以需要注意:

  1. BFS的时候,实际填入二维数组中的时候,题目的横纵坐标要互换。(原坐标系的(3,2), 相当于二维数组的第3列,第2行)
  2. 输出的时候,需要从最后一行开始输出,直到输出第0行,但是列的顺序不需要改变。
#include<bits/stdc++.h>
using namespace std;
int m=0,n=0,q=0;
char a[200][200];
int x=0,y=0;
char c='0';
int x1=0,x2=0,y1=0,y2=0;
struct point{
	int x,y;
	point(int _x,int _y){
		x=_x;
		y=_y;
	}
};
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
queue<point> qu;
void bfs()
{
	qu.push(point(x,y));
	while(!qu.empty())
	{
		point p=qu.front();
		qu.pop();
		for(int k =0;k<4;k++)
		{
			int nx=p.x;
		    int ny=p.y;
		    nx+=dx[k];
		    ny+=dy[k];
			if(nx>=0&&nx<m&&ny>=0&&ny<n&&a[ny][nx]!='|'&&a[ny][nx]!='-'&&a[ny][nx]!=c&&a[ny][nx]!='+')
			{                               
				a[ny][nx]=c;
				qu.push(point(nx,ny));
			}
		}
	
	}
	
}
int main()
{
//	freopen("15in.txt","r",stdin);
	scanf("%d%d%d",&m,&n,&q); 
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++)
		a[i][j]='.';
	}
	int cmd=0;
	for(int i=0;i<q;i++)
	{
		scanf("%d",&cmd);
		if(cmd==0)
		{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			if(x1==x2){
				int j=max(y1,y2);
				int k=min(y1,y2);
				for(;k<=j;k++)
				{
				  if(a[k][x1]!='-'&&a[k][x1]!='+')	a[k][x1]='|';
				  else a[k][x1]='+';	
				}
				  
			}
			else if(y1==y2){
				int k=max(x1,x2);
				int j=min(x1,x2);
				for(;j<=k;j++)
				{
					if(a[y1][j]!='|'&&a[y1][j]!='+')a[y1][j]='-'; //attention, original is plus,not replace
					else a[y1][j]='+';
				}
				  	
			}
			
//		for(int i=n-1;i>=0;i--)
//	      {
//	    for(int k=0;k<m;k++)
//		{
//	  	printf("%c",a[i][k]);
//	    }	
//	    printf("\n");
//         	}
	 
		}
		else if(cmd==1){
			
			char tmp;
			scanf("%d%d%c%c",&x,&y,&tmp,&c);
			bfs();	
			
//			for(int i=n-1;i>=0;i--)
//	      {
//	    for(int k=0;k<m;k++)
//		{
//	  	printf("%c",a[i][k]);
//	    }	
//	    printf("\n");
//         	}
//			 
			 	
		}
	
	}
	for(int i=n-1;i>=0;i--)
	{
	    for(int k=0;k<m;k++)
		{
	  	printf("%c",a[i][k]);
	    }	
	    printf("\n");
	}
	 
	  return 0;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值