loli的测试——搜索
今天是2018.5.24,loli给我们说要考搜索,本来以为是给初学者们考的就没准备,然而老师说我们也要考。(2018.6.29补:这次的简单测试与之后变得非常难的几次搜索测试形成了鲜明的对比,从而更深刻的说明了搜索的难度,使人印象深刻)
T1:N皇后问题
。。。这个没什么好说的,真的就是普通的N皇后问题,输出方案(n<=10),本来想用位运算保存行和斜线,但是怕在简单题上写炸于是就写了很朴素的做法。
# include <cstdio> # include <iostream> # include <cstring> using namespace std; int n,A=0; bool a[12]; bool b[30]; bool c[30]; int ans[12]; void write() { A++; for (int i=1;i<n;i++) printf("%d ",ans[i]); printf("%d\n",ans[n]); } void dfs(int x) { if(x==n+1) { write(); return ; } for (int i=1;i<=n;i++) { if(a[i]) continue; if(b[i+x]) continue; if(c[i-x+n]) continue; a[i]=true; b[i+x]=true; c[i-x+n]=true; ans[x]=i; dfs(x+1); a[i]=false; b[i+x]=false; c[i-x+n]=false; } } int main() { freopen("Queen.in","r",stdin); freopen("Queen.out","w",stdout); scanf("%d",&n); dfs(1); if(A==0) printf("no solute!\n"); fclose(stdin); fclose(stdout); return 0; }
T2:有重复元素的排列问题
和luogu上同名题目一模一样。然而考试时我问老师元素是不是只有'a'-'z', 他说不一定。。。那也好办,就按ascii码存一下,最大到300总够了吧,然而会很慢,于是。。。再记录一下最大最小值就OK啦,虽然还可以离散化一下,然而对于这道题不用。最神的是考完发了评测包发现数据中并没有任何奇怪的东西,就是只有'a'-'z'。当然这道题wzx还有另一种做法。。。next_permutation!然而loli测试不开O2所以悲哀的T了一个点,如果开O2的话这个函数大概是很快的。
# include <cstdio> # include <iostream> # include <cstring> # define R register int using namespace std; int tot=0,n,h=0,Max=0,Min=1000; char c; int vis[550]; char ans[550]; void write() { tot++; for (int i=1;i<=n;i++) printf("%c",ans[i]); printf("\n"); return ; } void dfs(int x) { if(x==n+1) { write(); return ; } for (R i=Min;i<=Max;i++) { if(vis[i]==0) continue; vis[i]--; ans[x]=(char)i; dfs(x+1); vis[i]++; } } int main() { scanf("%d",&n); for (R i=1;i<=n;i++) { c=getchar(); while (c==' '||c=='\n'||c=='\r') c=getchar(); Min=min(Min,(int)c); Max=max(Max,(int)c); vis[(int)c]++; } dfs(1); printf("%d\n",tot); return 0; }
T3:装箱问题
虽然是考搜索,可是这个题显然可以dp。
# include <cstdio> # include <iostream> # include <cstring> # define R register int using namespace std; int ans=0,n,c; int w[50]; bool dp[1005]; int main() { scanf("%d%d",&n,&c); for (R i=1;i<=n;i++) scanf("%d",&w[i]); dp[0]=true; for (R i=1;i<=n;i++) for (R j=c;j>=w[i];j--) dp[j]|=dp[j-w[i]]; for (R i=1;i<=c;i++) if(dp[i]) ans=i; printf("%d\n",ans); return 0; }
T4:字符序列
# include <cstdio> # include <iostream> # include <cstring> using namespace std; int n,tot=0; int ans[15]; void dfs(int x) { if(x==n+1) { tot++; return ; } for (int i=1;i<=3;i++) { if(x>=4&&ans[x-3]==ans[x-1]&&ans[x-2]==i) continue; ans[x]=i; dfs(x+1); } return ; } int main() { scanf("%d",&n); dfs(1); printf("%d\n",tot); return 0; }
T5:图的m着色问题
按照1-n搜索,每搜一个判一次可行性,竟然能过。。。事实上一个100的环是满足数据要求的,然而std也跑不了。
# include <cstdio> # include <iostream> # include <cstring> # define R register int using namespace std; const int maxn=105; struct edge { int too,nex; }g[maxn*maxn]; int tot=0,col[maxn],h=0,n,k,m,u,v,firs[maxn]; bool G[maxn][maxn]; bool vis[maxn]; void add(int u,int v) { g[++h].too=v; g[h].nex=firs[u]; firs[u]=h; } bool check(int x,int colo) { int j; for (R i=firs[x];i;i=g[i].nex) { j=g[i].too; if(vis[j]&&col[j]==colo) return false; } return true; } void dfs(int x) { if(x==n+1) { tot++; return ; } for (int i=1;i<=m;i++) { if(!check(x,i)) continue; vis[x]=true; col[x]=i; dfs(x+1); vis[x]=false; } } int main() { scanf("%d%d%d",&n,&k,&m); for (R i=1;i<=k;i++) { scanf("%d%d",&u,&v); if(G[u][v]) continue; G[v][u]=G[u][v]=true; add(u,v); add(v,u); } dfs(1); printf("%d\n",tot); return 0; }
因为有点感冒,出分前立了一个flag说如果没上400就趁机回家,然而上了...那也要回家!这可能是我第一次,也是最后一次AK。
---shzr