noip2015day1题解

晚上只睡了三个小时的情况下做的这套题(考试的时候做一会儿睡一会儿),觉得题很简单,半小时敲完一二题,结果第三道题的深搜一直没有搜出来qwq。。。。最后还是写了30分的暴力算法。。。。心态巨崩无比(本来以为自己可以AK的)

T1神奇的幻方

我相信只要会写程序的人都会做这道题(话说近几年的大模拟的题真的不少啊)

#include<cstdio>
const int MAXN=45;
int f[MAXN][MAXN];
int main()
{
	//freopen("magic.in","r",stdin);
	//freopen("magic.out","w",stdout);
	int n;
	std::scanf("%d",&n);
	int mid=(1+n)>>1;
	f[1][mid]=1;
	for(int i=2;i<=n*n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=n;k++)
			{
				if(f[j][k]==i-1)
				{
					if(j==1&&k!=n)
					{
						f[n][k+1]=i;
					}
					if(k==n&&j!=1)
					{
						f[j-1][1]=i;
					}
					if(j==1&&k==n)
					{
						f[j+1][k]=i;
					}
					if(j!=1&&k!=n)
					{
						if(f[j-1][k+1]==0)
						{
							f[j-1][k+1]=i;
						}
						else 
						{
							f[j+1][k]=i;
						}
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			printf("%d ",f[i][j]);
		}
		printf("\n");
	}
	return 0;
}

T2 信息传递

画一下图就能知道这道题的目的就是让求一个DAG里面的最小环,由于题目保证有解,所以直接tarjan缩点虐之(值得一提的是这道题出题人貌似没有卡数据,如果在递归的时候所有点全部进栈的话应该是会卡爆的),当然,并查集或者直接线性扫描都能过这题,当做水题刷就好了

#include<cstdio>
#include<algorithm>
const int MAXN=2e5+5;
struct Edge
{
	int nxt;
	int to;
}edge[MAXN<<1];
int num;
int head[MAXN];
void add(int from,int to)
{
	edge[++num].nxt=head[from];
	edge[num].to=to;
	head[from]=num;
}
int indx;
int color[MAXN];
int dgr[MAXN];
int dfn[MAXN];
int low[MAXN];
int stk[MAXN];
bool vis[MAXN];
int top;
int cnt;
void tarjan(int x)
{
	indx++;
	dfn[x]=low[x]=indx;
	stk[++top]=x;
	vis[x]=1;
	for(int i=head[x];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[x]=std::min(low[x],low[v]);
		}
		else
		if(vis[v])
		{
			low[x]=std::min(low[x],dfn[v]);
		}
	}
	if(dfn[x]==low[x])
	{
		cnt++;
		while(1)
		{
			int u=stk[top--];
			vis[u]=0;
			dgr[cnt]++;
			color[u]=cnt;
			if(u==x)
			{
				break;
			}
		}
	}
}
int main()
{
	//freopen("message.in","r",stdin);
	//freopen("message.out","w",stdout);
	int n;
	std::scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int ti;
		std::scanf("%d",&ti);
		add(i,ti);
	}
	for(int i=1;i<=n;i++)
	{
		if(!dfn[i])
		{
			tarjan(i);
		}
	}
	int ans=0x7fffffff;
	for(int i=1;i<=cnt;i++)
	{
		if(dgr[i]!=1&&dgr[i]<ans)
		{
			ans=dgr[i];
		}
	}
	printf("%d\n",ans);
	return 0;
}

T3 斗地主

究极大模拟。。。。据说剪枝以后的状压+dfs能过95分,不过正解是贪心+dfs暴搜,由于内存和时间都不算紧张,所以说最后的答案就完全靠细不细心了(然而样例2的答案一直少了1,最后发现就是单纯的没有加而已。。。)

#include<cstdio>
#include<cstring>
#include<algorithm>
int T,n;
int cnt[16];
int ans=23;
void dfs(int x)
{
	if(x>ans)
	{
		return;
	}
	int s1;
	int s2;
	int s3;
	int s4;
	s1=s2=s3=s4=0;
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==2)
		{
			s2++;
		}
		if(cnt[i]==1)
		{
			s1++;
		}
	}
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==4)
		{
			s4++;
			if(s1>=2)
			{
				s1-=2;
			}
			else if(s2>=2)
			{
				s2-=2;
			}
			else if(s2>=1)
			{
				s2--;
			}
		}
	}
	for(int i=1;i<=14;i++)
	{
		if(cnt[i]==3)
		{
			s3++;
			if(s1>=1)
			{
				s1--;
			}
			else if(s2>=1)
			{
				s2--;
			}
		}
	}
	ans=std::min(ans,x+s1+s2+s3+s4);
	int j;
	for(int i=1;i<=8;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]--;
			if(cnt[j]<0)
			{
				break;
			}
			if(j-i>=4)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i)cnt[j--]++;
	}
	for(int i=1;i<=10;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]-=2;
			if(cnt[j]<0) break;
			if(j-i>=2)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i) cnt[j--]+=2;
	}
	for(int i=1;i<=11;i++)
	{
		for(j=i;j<=12;j++)
		{
			cnt[j]-=3;
			if(cnt[j]<0)
			{
				break;
			}
			if(j-i>=1)
			{
				dfs(x+1);
			}
		}
		if(j==13)
		{
			j--;
		}
		while(j>=i)
		{
			cnt[j--]+=3;
		}
	}
}
int main()
{
	//freopen("landlords.in","r",stdin);
	//freopen("landlords.out","w",stdout);
	int T,n;
	std::scanf("%d%d",&T,&n);
	while(T--)
	{
		std::memset(cnt,0,sizeof(cnt));
		ans=23;
		for(int i=1;i<=n;i++)
        {
	        int x,y;
	        std::scanf("%d%d",&x,&y);
	        if(x==0)
	        {
		        cnt[14]++;
	        }
	        else 
	        if(x==1)
	        {
		        cnt[12]++;
	        }
	        else 
		    if(x==2)
	        {
		        cnt[13]++;
	        }
	        if(x>=3)
	        {
		        cnt[x-2]++;
	        }
        }
		dfs(0);
		printf("%d\n",ans);
	}
	return 0;
}
/*
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1

1 17
12 3
4 3
2 3
5 4
10 2
3 3
12 2
0 1
1 3
10 1
6 2
12 1
11 3
5 2
12 4
2 2
7 2
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!对于扫雷游戏的题解,我可以给你一些思路和代码示例。首先,你需要了解扫雷游戏的规则和要求。接下来,你可以使用C++语言来实现游戏逻辑和界面。 下面是一个简单的扫雷游戏的C++代码示例: ```cpp #include <iostream> #include <vector> #include <random> using namespace std; class MinesweeperGame { private: int rows; int cols; vector<vector<char>> board; vector<vector<bool>> revealed; vector<pair<int, int>> directions = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; public: MinesweeperGame(int m, int n, int mineCount) { rows = m; cols = n; board.resize(rows, vector<char>(cols, ' ')); revealed.resize(rows, vector<bool>(cols, false)); placeMines(mineCount); calculateNumbers(); } void printBoard() { cout << " "; for (int j = 0; j < cols; j++) { cout << j << " "; } cout << endl; for (int i = 0; i < rows; i++) { cout << i << " |"; for (int j = 0; j < cols; j++) { cout << board[i][j] << "|"; } cout << endl; } } bool isGameOver() { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (board[i][j] == 'M' && revealed[i][j]) { return true; } } } return false; } void reveal(int row, int col) { if (row < 0 || row >= rows || col < 0 || col >= cols || revealed[row][col]) { return; } revealed[row][col] = true; if (board[row][col] == 'M') { return; } if (board[row][col] == '0') { for (auto dir : directions) { reveal(row + dir.first, col + dir.second); } } } private: void placeMines(int mineCount) { random_device rd; mt1

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值