CCF 201312题解

题目链接:首页 - 计算机软件能力认证考试系统

201312-1

思想:①si的数据范围小,可以用数组记录

②找2个变量一个记录次数一个记录大小。

代码:略

201312-2

思想: 直接按照题目要求模拟去判断,输出的时候需要判断最后一位是哪个。

代码:略

201312-3

 思想:让你求最大的连续矩形。

       ①可以直接用单调栈计算比当前小的最右边和最左边的位置,然后最后去算

        ②可以直接单调栈计算,但是需要在最后更新一下最左边的高度。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int a[maxn],b[maxn];
int main()
{
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i];
	int ans=0;
	a[n]=0;
	stack<int>st;
	for(int i=0;i<=n;i++)
	{
		if(st.empty() || a[st.top()] <= a[i])
			st.push(i);
		else
		{
			int index,num;
			while(!st.empty() && a[st.top()] > a[i])
			{
				index=st.top();
				num=a[index];
				st.pop();
				int sum=(i-index)*num;
				if(sum>ans)
					ans=sum;
			}
			st.push(index);//更新最左边那个的高度,不懂可以画下图
			a[index]=a[i];
		}
	}
	printf("%d\n",ans);
	return 0;
} 

 

 201312-4

思想:先考虑羁绊关系,0必须出现在1前边,2必须出现在3前边,最高位不能为0,四种数字最少一次,那么第一位只能是2。

我们考虑有哪几种情况是满足条件的。

〇只有2

①由2和0组成且0不是最高位

②由2和3组成

③由2和0和3组成且0不是最高位

④由2和0和1组成且0不是最高位

⑤由2和0和3和1组成且0不是最高位

dp[n][m] 代表的是n位的情况下当前是第m种情况的方案数

对于dp[n][0]这种情况只能由dp[n-1][0]加一个2转移过来                                            就有1种方案

对于dp[n][1]这种情况可以由dp[n-1][0]加一个0 和 dp[n-1][1] 加0/2转移过来              就有3种方案

对于dp[n][2]这种情况可以由dp[n-1][0]加一个3过来和dp[n-1][2]加3转移过来             就有2种方案

对于dp[n][3]这种情况可以由dp[n-1][1]加一个3过来和dp[n-1][2]加一个0过来和dp[n-1][3]加一个0/2过来                                                                                                                        就有4种方案

对于dp[n][4]这种情况可以由dp[n-1][1]加一个3过来和dp[n-1][4]加1/2过来                  就有3种方案

对于dp[n][5]这种情况可以由dp[n-1][3]加一个1过来和dp[n-1][4]加3过来和dp[n-1][5]加2/3过来                                                                                                                                        就有4种方案

代码:

#include<bits/stdc++.h>
using namespace std;
long long mod = 1e9+7;
long long dp[1005][6];
int main()
{
    long long n;
    cin>>n;
    for(int i=1;i<=n;i++)
     {
        dp[i][0] = 1;
        dp[i][1] = (dp[i-1][0] + dp[i-1][1] * 2) % mod;
        dp[i][2] = (dp[i-1][0] + dp[i-1][2]) % mod;
        dp[i][3] = (dp[i-1][1] + dp[i-1][2] + dp[i-1][3] * 2) % mod;
        dp[i][4] = (dp[i-1][1] + dp[i-1][4] * 2) % mod;
        dp[i][5] = (dp[i-1][3] + dp[i-1][4] + dp[i-1][5] * 2) % mod;
    }
    cout<<dp[n][5]<<endl;
    return 0;
 }

        

 201312-5

题意:如果从S不能到T就输出i am stuck,如果能到的话就需要计算能从S到达K,但是K到达不了T的数量数。先BFS用vis1标记S可以到达的点,然后对于所有标记的点在暴力BFS检验是否可以到达T点。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
char s[55][55];
int vis1[55][55];
int vis2[52][52];
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int x,y,x1,y1,n,m;
struct point{
	int x;
	int y;
};
void dfs()
{
	queue<point>q;
	q.push(point{x,y});
	vis1[x][y]=1;
	while(!q.empty())
	{
		point temp = q.front();q.pop();
		int tx=temp.x;int ty=temp.y;
		int t1=0,t2=4;
		if(s[tx][ty]=='-')
			t1=2;
		if(s[tx][ty]=='|')
			t2=2;
		if(s[tx][ty]=='.')
			t1=1,t2=2;
		for(int i=t1;i<t2;i++)
		{
			int dx=tx+dir[i][0];
			int dy=ty+dir[i][1];
			if(dx>=0 && dx<n && dy>=0 && dy<m && s[dx][dy]!='#' && !vis1[dx][dy])
				vis1[dx][dy]=1,q.push(point{dx,dy}); 
		}
	}
}
void dfs1(int xx,int yy)
{
	queue<point>q;
	q.push(point{xx,yy});
	vis2[xx][yy]=1;
	while(!q.empty())
	{
		point temp = q.front();
		q.pop();
		int tx=temp.x;
		int ty=temp.y;
		vis2[tx][ty]=1;
		int t1=0,t2=4;
		if(s[tx][ty]=='-')
			t1=2;
		if(s[tx][ty]=='|')
			t2=2;
		if(s[tx][ty]=='.')
			t1=1,t2=2;
		for(int i=t1;i<t2;i++)
		{
			int dx=tx+dir[i][0];
			int dy=ty+dir[i][1];
			if(dx>=0 && dx<n && dy>=0 && dy<m && s[dx][dy]!='#' && !vis2[dx][dy])
				vis2[dx][dy]=1,q.push(point{dx,dy}); 
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
		scanf("%s",s[i]);
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(s[i][j]=='S')
			{
				x=i;
				y=j;
			}
			if(s[i][j]=='T')
			{
				x1=i;
				y1=j;
			}
		}
	}
	dfs();
	if(!vis1[x1][y1])
		printf("I'm stuck!\n");
	else
	{
		int ans = 0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				if(vis1[i][j])
				{
					memset(vis2,0,sizeof(vis2));
					dfs1(i,j); 
					if(!vis2[x1][y1])
						ans++;
				}
			}
		}
		printf("%d\n",ans); 
	}
	return 0;	
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值