马走日
#include<iostream>
#include<cstring>
using namespace std;
const int N=25;
int n,m;
char a[N][N];
bool vis[N][N];
int nx[]={-2,-1,1,2,2,1,-1,-2};
int ny[]={1,2,2,1,-1,-2,-2,-1};
int res=0;
void dfs(int x,int y,int cnt)
{
if(cnt==n*m)
{
res++;return;
}
vis[x][y]=true;
for(int k=0;k<8;k++)
{
int qx=x+nx[k],qy=y+ny[k];
if(!vis[qx][qy]&&qx>=0&&qx<=n-1&&qy>=0&&qy<=m-1)
dfs(qx,qy,cnt+1);
}
vis[x][y]=false;
return;
}
int main()
{
int t;cin>>t;
while(t--)
{
res=0;
cin>>n>>m;
int x,y;cin>>x>>y;
dfs(x,y,1);
cout<<res<<endl;
}
}
单词接龙
两个单词首尾相同可以连接,给定开始字符,每个单词最多用2次,求组合单词最长度
#include<iostream>
using namespace std;
int n;
const int N=25;
string str[N];
int g[N][N];
int used[N];
int ans=0;
void dfs(string s,int last)
{
ans=max((int)s.size(),ans);
used[last]++;//标记
for(int i=1;i<=n;i++)
if(g[last][i]&&used[i]<2)
dfs(s+str[i].substr(g[last][i]),i);
used[last]--;//恢复
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>str[i];
char start;cin>>start;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
string a=str[i],b=str[j];
for(int k=1;k<min(a.size(),b.size());k++)
if(a.substr(a.size()-k,k)==b.substr(0,k))
{
g[i][j]=k;//i和j可以相连,且从第k个字母开始
break;
}
}
for(int i=1;i<=n;i++)
if(str[i][0]==start)
dfs(str[i],i);
cout<<ans;
}
分成互质组
#include<iostream>
using namespace std;
const int N=15;
int n;
int p[N];
int group[N][N];
bool vis[N];
int ans=N;
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
bool check(int group[],int gc,int x)
{
for(int i=0;i<gc;i++)
if(gcd(p[group[i]],p[x])>1)
return false;
return true;
}
//第g组 当前组内下标 当前搜完元素个数 从哪个元素开始搜
void dfs(int g,int gc,int tc,int start)
{
if(g>=ans) return;
if(tc==n) ans=g;
bool flag=true;
for(int i=start;i<n;i++)
if(!vis[i]&&check(group[g],gc,i))
{
vis[i]=true;
group[g][gc]=i;
dfs(g,gc+1,tc+1,i+1);
vis[i]=false;
flag=false;
}
if(flag) dfs(g+1,0,tc,0);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>p[i];
dfs(1,0,0,0);
cout<<ans;
}