SDUT 2021 Summer Individual Contest - 8

C - chokudai

题意:
给你一个字符串(长度<1e5),问有几个子序列是 ”chokudai" ,答案取余1e9+7

输入
chchokudai
输出
3

分析:
简单DP,除了第一个字母,其他字母都是上一个字母出现数量与该字母数量的和,代码很好理解

#include<iostream>
using namespace std;
const int mod=1e9+7;
int ans[8];
int main()
{
     string s;
     cin >> s;
     for(int i=0;i<s.size();i++)
     {
         if(s[i]=='c') ans[0]++;
         else if(s[i]=='h')  ans[1]=(ans[1]+ans[0])%mod;
         else if(s[i]=='o') ans[2]=(ans[2]+ans[1])%mod;
         else if(s[i]=='k') ans[3]=(ans[3]+ans[2])%mod;
         else if(s[i]=='u') ans[4]=(ans[4]+ans[3])%mod;
         else if(s[i]=='d') ans[5]=(ans[5]+ans[4])%mod;
         else if(s[i]=='a') ans[6]=(ans[6]+ans[5])%mod;
         else if(s[i]=='i') ans[7]=(ans[7]+ans[6])%mod;   
     }
     cout<<ans[7]<<endl;
     return 0;
}

D - Number of Shortest paths

题意:
一幅图,有n个点m条双向边(n=[2,2e5],m=[0,2e5]),边长都是1,问第一个点到第n个点的最短路线的数量是多少,答案取模1e9+7

输入
4 5 (n个点,m条边,接下来m行)
2 4
1 2
2 3
1 3
3 4
输出
2
注:1->2->4 and 1->3->4

分析:
用bfs搜最短路

#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
const int N=8e5+10;
const int M=1e9+7;
int h[N],ne[N],e[N],idx;
void add(int a,int b)
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}
int n,m;
int dist[N],ans[N];//ans表示1到当前下标点的最短路径的方案数 
bool st[N];
queue<int> q;
void bfs(int x)
{
	q.push(x);
	dist[x]=0;
	st[x]=true;
	ans[x]=1;//初始化 
	while(q.size())
	{
		int t=q.front();
		q.pop();
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(!st[j])
			{
				dist[j]=dist[t]+1;
				ans[j]=ans[t];//如果没有遍历过j点,那么1~j的方案数==1~t的方案数 
				q.push(j); 
				st[j]=true;
			}
			else//若已经遍历过且距离==当前根节点的距离+1,那么1~j的方案数=1~j的方案数=+1~t的方案数
			{
				if(st[j]&&dist[j]==dist[t]+1)
				{
					ans[j]=(ans[j]+ans[t])%M;
				}
			}
		}
	}
}
int main()
{
	memset(h,-1,sizeof(h));
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	bfs(1);
	cout<<ans[n]<<endl;
}

E - Red Polyomino

题意:
给你一个n*n的矩阵(n=[1,8])和一整数k,矩阵中的元素值为 **#**的点是不可选择的点,问:有多少个大小为k的连通块(这里大小指元素数)

输入
3 (n)
5(k)(接下来是n*n的矩阵)
#.#

…#
输出
5
注释:从6个点种选择 5 (k) 个点,方案有6种,但是只有5种是连通的,所以输出5

分析:
一开始我的想法是从所有可以选择的点中选k个,用dfs搜到所有方案,再对每一个方案判断是否连通块,TLE了
后来换了一下思路,如果我能在dfs找方案的时候保证找到的每一个方案是连通块,那么就可以减少很多时间复杂度,代码如下

#include<iostream>
#include<unordered_map>
#include<queue>
#include<string.h>
using namespace std;
const int N=9;
unordered_map<string,int> mp;//因为在搜索过程很容易搜到重复情况,所以用哈希表存一下 
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};//下上右左
char a[N][N];
bool st[N][N];
long long n,k,ans;
string jihe()//将二维矩阵压缩成一维的字符串 
{
	string an;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			an+=a[i][j];
	return an;
}
void dfs(int s)
{
	string tmp=jihe();
	if(mp[tmp]>=1) return ;//如果存过直接return 
	mp[tmp]=1;
	if(s==0) 
	{
		ans++;
		return ;
	} 
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]!='.') continue;
			for(int k=0;k<4;k++)
			{
				int x=i+dx[k],y=j+dy[k];
				if(x>=0&&y>=0&&x<n&&y<n&&a[x][y]=='@')//这句的意义是a[i][j]是. 且他附近至少有一个@才会将a[i][j]变成@ 
				{
					a[i][j]='@';
					dfs(s-1);
					a[i][j]='.';
				}
			}
		}
	}
}
int main()
{
	cin>>n>>k;
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]=='.')
			{
				a[i][j]='@';
				dfs(k-1);
				a[i][j]='.';
			}
		}
	}
	cout<<ans<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值