Codeforces Round #454 Div. 1 [ 906A A. Shockers ] [ 906B B. Seating of Students ] [ 906C C. Party ]

PROBLEM A. Shockers

  http://codeforces.com/contest/906/problem/A

  906A

  907C

  水题,按照题意模拟一下就行了

  如果是 ‘ ! ’,那么该字符串中所有没出现的字符标记为否,如果是 ' . '那么该字符串中出现的字符全部标记为否

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>

using namespace std;

const int M=40;
const int N=26;
const int MLEN=1e5+44;

int flag[M];
int n,len;
char str[MLEN];
bool ed;
int tag[M];

int main()
{
	char op[2];
	int ans=0;
	for(int i=0;i<26;i++)
		flag[i]=1;
	scanf("%d",&n);
	ed=false;
	for(int i=1;i<n;i++)
	{
		scanf("%s%s",op,str);
		len=strlen(str);
		if(op[0]=='!')
		{
			if(ed)
			{
				ans++;
				continue;
			}
			memset(tag,0,sizeof(tag));
			for(int j=0;j<len;j++)
				tag[str[j]-'a']++;
			for(int j=0;j<N;j++)
				if(tag[j]==0) flag[j]=0; 
		}
		else if(op[0]=='.')
		{
			if(ed) continue;
			for(int j=0;j<len;j++)
				flag[str[j]-'a']=0;
		}
		else
		{
			if(ed)
			{
				ans++;
				continue;
			}
			for(int j=0;j<len;j++)
				flag[str[j]-'a']=0;
		}
		if(ed==0)
		{
			int tmp=0;
			for(int i=0;i<26;i++)
				if(flag[i]) tmp++;
			if(tmp==1)
				ed=1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

  

PROBLEM B. Seating of Students

  http://codeforces.com/contest/906/problem/B

  906B

  907D

  n为行数,m为列数

  如果 n,m 的值都小于等于 4 的话,直接 dfs 暴力跑一下即可

  否则,如果 m>n 那么对于第 x 行,记该行元素为 a1,a2,a3,a4,……am,提取下标为奇数的为一组 a1,a3,a5,a7……,提取下表为偶数的为另一组 a2,a4,a6……

    如果行号 x 为奇数,则将奇数组放在偶数组前面,组成新的一行,即 a1,a3,a5,a7……,a2,a4,a6……

    如果行号 x 为偶数,则将奇数组放再偶数组后面,组成新的一行,即 a2,a4,a6……,a1,a3,a5……

  如果 n>m 则类似地对每一列处理

  (对于 a1,a2,a3,a4,……ak,如果 k>4,上述重组方法是必然合法的)

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;
namespace solvesmall
{
	const int M=24;

	int n,m,tol;
	int mtx[M][M],mdl[M][M];
	int dx[4]={0,0,-1,1};
	int dy[4]={-1,1,0,0};
	int flag[M];
	int ng[M][M];
	
	bool dfs(int x,int y)
	{
		int xx,yy,ngflag;
		if(x>n) return true;
		for(int i=1;i<=tol;i++)
			if(flag[i]==0)
			{
				ngflag=0;
				for(int p=0;p<4;p++)
				{
					xx=x+dx[p]; yy=y+dy[p];
					if(ng[i][mtx[xx][yy]])
						ngflag=1;
				}
				if(ngflag==0)
				{
					mtx[x][y]=i;
					flag[i]=1;
					xx=x; yy=y+1;
					if(yy==m+1) xx++,yy=1;
					if(dfs(xx,yy)) return true;
					mtx[x][y]=0;
					flag[i]=0;
				}
			}
		return false;
	}
	
	void getng()
	{
		int xx,yy;
		memset(ng,0,sizeof(ng));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				for(int p=0;p<4;p++)
				{
					xx=i+dx[p]; yy=j+dy[p];
					if(mdl[xx][yy]!=0)
						ng[mdl[i][j]][mdl[xx][yy]]=1;
				}
			}
	}

	int solve(int xn,int xm)
	{
		n=xn,m=xm;
		int tmp;
		tmp=0; tol=n*m;
		memset(mtx,0,sizeof(mtx));
		memset(mdl,0,sizeof(mdl));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
			{
				tmp++;
				mdl[i][j]=tmp;
			}
		getng();
		memset(flag,0,sizeof(flag));
		if(dfs(1,1))
		{
			puts("YES");
			for(int i=1;i<=n;i++)
			{
				for(int j=1;j<=m;j++)
					printf("%d ",mtx[i][j]);
				puts("");
			}
		}
		else
			puts("NO");
	}
}

const int M=1e5+44;

int n,m;
int pi[M];
vector<int> ans;

void puts1(int li,int ri)
{
	int cnt=0;
	for(int i=li;i<=ri;i+=2)
	{
		if(cnt++) printf(" ");
		printf("%d",i);
	}
}

void puts2(int li,int ri)
{
	int cnt=0;
	for(int i=li+1;i<=ri;i+=2)
	{
		if(cnt++) printf(" ");
		printf("%d",i);
	}
}

int getpos(int x,int y)
{
	return ((x-1)*m+y);
}

int main()
{
	int li,ri;
	scanf("%d%d",&n,&m);
	if(n<=4 && m<=4)
	{
		solvesmall::solve(n,m);
		return 0;
	}
	if(m>n)
	{
		printf("YES
");
		for(int i=1;i<=n;i++)
		{
			li=(i-1)*m+1; ri=i*m;
			if(i&1)
				puts1(li,ri),printf(" "),puts2(li,ri),printf("
");
			else 
				puts2(li,ri),printf(" "),puts1(li,ri),printf("
");	
		}
	}
	else
	{
		printf("YES
");
		ans.clear();
		for(int i=1;i<=m;i++)
			pi[i]=((i-1)&1)+1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				ans.push_back(getpos(pi[j],j));
				pi[j]+=2;
				if(pi[j]>n)
					pi[j]=(j&1)+1;
			}
		}
		for(int i=0;i<ans.size();i++)
		{
			printf("%d",ans[i]);
			if((i+1)%m==0)
				printf("
");
			else printf(" ");
		}
	}
	return 0;
}

  

 

PROBLEM C. Party

  http://codeforces.com/contest/906/problem/C

  906C

  907E

  其实质就是一个图,然后确定一个团,每次要找到团中的一个点,把这个点所连的所有点都加入到这个团中,求把所有点加入到团中所需的最少操作数

  由于点最多只有 22 个,可以状态压缩,然后对于每个点可以构造一个初始状态,从所有初始状态开始跑一遍带记忆化的 bfs 即可。

 

#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;

const int N=(1<<22);
const int M=24;

int n,m;
int dp[N+44],op[N+44],lst[N+44];
int val[M];
queue<int> que;
int stk[M],lstk;

void bfs()
{
	memset(dp,0,sizeof(dp));
	memset(op,-1,sizeof(op));
	memset(lst,-1,sizeof(lst));
	while(!que.empty()) que.pop();
	for(int i=0;i<n;i++)
	{
		dp[val[i]]=1; op[val[i]]=i;
		que.push(val[i]);
	}
	int now,tmp,tmpdp,tmpnow;
	while(!que.empty())
	{
		now=que.front(); que.pop();
		for(int i=0;i<n;i++)
		{
			if(now&(1<<i))
			{
				tmpnow=now|val[i];
				if(dp[tmpnow]==0)
				{
					dp[tmpnow]=dp[now]+1;
					op[tmpnow]=i;
					lst[tmpnow]=now;
					que.push(tmpnow);
					if(tmpnow==((1<<n)-1))
						return ;
				}
			}
		}
	}
}

int main()
{
	int a,b,tmp;
	scanf("%d%d",&n,&m);
	memset(val,0,sizeof(val));
	for(int i=0;i<n;i++)
		val[i]|=(1<<i);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		a--,b--;
		val[a]|=(1<<b);
		val[b]|=(1<<a);
	}
	if(m==n*(n-1)/2)
	{
		printf("0
");
		return 0;
	}
	bfs();
	lstk=0;
	tmp=(1<<n)-1;
	while(tmp!=-1)
	{
		stk[++lstk]=op[tmp];
		tmp=lst[tmp];
	}
	printf("%d
",lstk);
	while(lstk)
	{
		printf("%d",stk[lstk]+1);
		lstk--;
		if(lstk!=0) printf(" ");
		else printf("
");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/FxxL/p/8095418.html