Atcoder ABC 291

Atcoder ABC 291

D

题意

n张牌,每张牌两面都有数字,可以翻面,问有多少种情况使得这n张牌中每相邻两张牌表面上的数互不相同

思路

线性dp,每次比较当前位和上一位是否相同即可。
唉,看漏条件了,没看到相邻,想得太复杂了。
但又可以想一想,如果去掉相邻这个条件,这个题要怎么做。

代码

void solve() 
{
	cin>>n;
	for(int i=1;i<=n;i++) 
	{
		cin>>a[i]>>b[i];
	}
	f[1][0]=f[1][1]=1;//初始化不是从0开始
	for(int i=2;i<=n;i++) 
	{
		if(a[i]!=a[i-1]) f[i][0]=(f[i][0]+f[i-1][0])%mod;
		if(a[i]!=b[i-1]) f[i][0]=(f[i][0]+f[i-1][1])%mod;
		if(b[i]!=a[i-1]) f[i][1]=(f[i][1]+f[i-1][0])%mod;
		if(b[i]!=b[i-1]) f[i][1]=(f[i][1]+f[i-1][1])%mod;
	}
	cout<<(f[n][0]+f[n][1])%mod<<endl;
}

E

题意

一个长度为n的数组,每个数都是(1~n)且互不相同,给出m个关系,\(x<y\)表示\(a_x<a_y\) ,为是否可以通过这些关系确定该数组。

思路

一开始以为差分约束,打了一发,超时了,后来一想情况没那么复杂,拓扑排序一下就好了。
不行的情况:
1.入度为0的点有多个或者没有
2.有环。但因为用了拓扑排序就不用特意判环了,有环就会出现数组中某些位置的值会重复。

代码

int h[N],e[N],ne[N],idx;
int dis[N],in[N];
bool vis[N];
map<pii,int> mp;//去重边

void add(int a,int b) 
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx++;
}

bool toph_() 
{
	int cnt=0,rt=0;
	for(int i=1;i<=n;i++) 
	{
		if(!in[i]) rt=i,cnt++;
	}
	if(cnt>1||rt==0) return false;
	queue<int> que;
	que.push(rt);
	dis[rt]=1;
	while(que.size())
	{
		int u=que.front();
		que.pop();
		for(int i=h[u];i!=-1;i=ne[i]) 
		{
			int j=e[i];
			if(--in[j]==0) 
			{
				que.push(j);
				dis[j]=dis[u]+1;
			}
		}
	}
	return true;
}

void solve() 
{	
	memset(h,-1,sizeof(h));
	cin>>n>>m;
	for(int i=1;i<=m;i++) 
	{
		int x,y;
		cin>>x>>y;
		if(mp.count({x,y})) continue;
		mp[{x,y}]=1;
		add(x,y);
		in[y]++;
	}
	if(!toph_()) cout<<"No\n";
	else 
	{
		for(int i=1;i<=n;i++) 
		{
			if(vis[dis[i]]) {cout<<"No\n";return;}
			vis[dis[i]]=1; 
		}
		cout<<"Yes\n";
		for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
		cout<<endl;
	}
}

F 补

题意

给出n个字符串,如果\(s_{ij}=1\) 则表示第i个点可以到第i+j个点
问不经过点k是否有一条从1到n的路径,如果有就求最短的,没有就-1,k=2,3,4...n-1

思路

真的是个弱鸡啊,脑子不够用了,溜去看大佬代码了。
bfs求 1到各个点的最短路\(d1\),建反图求 n到其它点的最短路\(d2\)
对于x到y,如果\(d1_x\)存在且\(d2_y\) 存在,那么它们连在一起+1就等于从1到n了,可以确定的是,这条路径没有经过\([x+1,y-1]\)

代码

int n,m; 
vector<int> bfs(vector<vector<int>> &a,int s) 
{	
	vector<int> dis(n,-1);
	dis[s]=0;
	queue<int> que;
	que.push(s);
	while(que.size()) 
	{
		int u=que.front();
		que.pop();
		for(auto &x:a[u]) 
		{
			if(dis[x]==-1) 
			{	
				dis[x]=dis[u]+1;
				que.push(x);
			}
		}
	}
	return dis; 
}

void solve() 
{
	cin>>n>>m;
	vector<vector<int>> a1(n),a2(n);
	for(int i=0;i<n;i++) 
	{
		string s;
		cin>>s;
		for(int j=0;j<m;j++) 
		{
			if(s[j]=='1') 
			{
				a1[i].push_back(i+j+1);
				a2[i+j+1].push_back(i);
			}
		}
	}
	vector<int> d1,d2,ans(n,-1);
	d1=bfs(a1,0);
	d2=bfs(a2,n-1);	

	for(int i=0;i<n;i++) 
	{
		for(auto &x : a1[i]) 
		{	
			if(d1[i]==-1||d2[x]==-1) continue;
			int res=d1[i]+d2[x]+1;
			for(int j=i+1;j<x;j++) 
			{
				if(ans[j]==-1||ans[j]>res)
				{
					ans[j]=res;
				}
			}
		}
	}
	for(int i=1;i<n-1;i++) cout<<ans[i]<<" ";
	cout<<endl;
}

G 待补

posted @ 2023-02-27 11:12  Liang2003  阅读(52)  评论(0编辑  收藏  举报