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\n"); 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("\n"); else puts2(li,ri),printf(" "),puts1(li,ri),printf("\n"); } } else { printf("YES\n"); 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("\n"); 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\n"); return 0; } bfs(); lstk=0; tmp=(1<<n)-1; while(tmp!=-1) { stk[++lstk]=op[tmp]; tmp=lst[tmp]; } printf("%d\n",lstk); while(lstk) { printf("%d",stk[lstk]+1); lstk--; if(lstk!=0) printf(" "); else printf("\n"); } return 0; }