1.迷宫
一道dfs的题目
#include<bits/stdc++.h>
using namespace std;
#define maxn 10
string str = "UDDLUULRULUURLLLRRRURRUURLDLRDRUDDDDUUUUURUDLLRRUUDURLRLDLRLULLURLLRDURDLULLRDDDUUDDUDUDLLULRDLUURRR";
char maps[10][10];
int vis[10][10];
int cou=0;
void dfs(int x,int y){
if(vis[x][y]==1) return;
if(x<0||x>9||y<0||y>9){
cou++;
return;
}
vis[x][y]=1;
switch(maps[x][y]){
case 'U':
x-=1;
break;
case 'D':
x+=1;
break;
case 'L':
y-=1;
break;
case 'R':
y+=1;
break;
default:
break;
}
dfs(x,y);
}
int main(){
int index;
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
index=i*10+j;
maps[i][j]=str[index];
}
}
for(int i=0;i<10;i++){
for(int j=0;j<10;j++){
memset(vis,0,sizeof(vis));
dfs(i,j);
}
}
cout<<cou<<endl;
}
2 跳蚱蜢
可以将蚱蜢跳看做是盘子在跳,将初次摆放顺序看作012345678,最后的摆放顺序看作087654321,用bfs的方法解答
#include<bits/stdc++.h>
using namespace std;
struct node
{
string s;
int t;
node(string ss, int tt){
s = ss, t = tt;
}
};
map<string,bool> mp;
queue<node> q;
void f()
{
while(!q.empty()){
node now = q.front();
q.pop();
string s = now.s;int t = now.t;
if(s == "087654321"){
cout<<t<<endl;
break;
}
int i;
for(i=0;i<10;i++){
if(s[i]=='0') break;
}
for(int j=i-2;j<=i+2;j++){
int k = (j+9)%9;
if(k==i) continue;
char tmp;
tmp=s[i];s[i]=s[k];s[k]=tmp;
if(!mp[s]){
mp[s] = true;
q.push(node(s,t+1));
}
tmp=s[i];
s[i]=s[k];
s[k]=tmp;
}
}
}
int main(){
string s = "012345678";
q.push(node(s, 0));
mp[s] = true;
f();
}
3 方块切割
观察发现每一个符合条件的切法都经过(3,3)
于是用dfs从(3,3)开始搜索,直到搜到边界,注意走到一个点时其关于(3,3)的另一个点也要标记,否则无法对称,最后结果要除以4,因为旋转对称的只算一种
#include<bits/stdc++.h>
using namespace std;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int maps[10][10];
int ans=0;
void dfs(int x,int y){
if(x==0||x==6||y==0||y==6){
ans++;
return;
}
for(int i=0;i<4;i++){
int dx=x+dir[i][0];
int dy=y+dir[i][1];
if(maps[dx][dy]==0){
maps[dx][dy]=1;
maps[6-dx][6-dy]=1;
dfs(dx,dy);
maps[dx][dy]=0;
maps[6-dx][6-dy]=0;
}
}
}
int main(){
maps[3][3]=1;
dfs(3,3);
cout<<ans/4<<endl;
}
4.字母组串
一种递归的思想,长度为n的字串由长度为n-1的子串分别加上a,b,c变化而来
#include <stdio.h>
int f(int a, int b, int c, int n)
{
if(a<0 || b<0 || c<0) return 0;
if(n==0) return 1;
return f(a-1,b,c,n-1) + f(a,b-1,c,n-1) + f(a,b,c-1,n-1);
}
int main()
{
printf("%d\n", f(1,1,1,2));
printf("%d\n", f(1,2,3,3));
return 0;
}
5 最大公共子串
#include <stdio.h>
#include <string.h>
#define N 256
int f(const char* s1, const char* s2)
{
int a[N][N];
int len1 = strlen(s1);
int len2 = strlen(s2);
int i,j;
memset(a,0,sizeof(int)*N*N);
int max = 0;
for(i=1; i<=len1; i++){
for(j=1; j<=len2; j++){
if(s1[i-1]==s2[j-1]) {
a[i][j] =a[i-1][j-1]+1;
if(a[i][j] > max) max = a[i][j];
}
}
}
return max;
}
int main()
{
printf("%d\n", f("abcdkkk", "baabcdadabc"));
return 0;
}
6.正则问题
题目理解:遇到“|”就比较其左右两边的大小 如样例((xx|xxx)x|(x|xx))xx
(xx|xxx)的长度为3,遇到x加上1得4,(x|xx)=2,4|2=4,遇到
xx得到6
题解:用递归的方式求解,遇到‘(’时就递归到下一层,如果是x就用一个temp记录x的个数,遇到“|”时,由于“|”右边要和左边的x个数比大小,就用一个m记录左边的值,遇到右括号的时候就比较两个大小,返回较大的那一个
#include<bits/stdc++.h>
using namespace std;
string s;
int len;
int pos;
int f(){
int m=0;
int temp=0;
while(pos<len){
if(s[pos]=='('){
pos++;
temp+=f();
}
else if(s[pos]=='x'){
pos++;
temp++;
}
else if(s[pos]=='|'){
pos++;
m=max(m,temp);
temp=0;
}
else if(s[pos]==')'){
pos++;
m=max(m,temp);
return m;
}
}
m=max(m,temp);
return m;
}
int main(){
cin>>s;
len=s.size();
int ans=f();
cout<<ans<<endl;
}
7 包子凑数
如果输入的数的最大公约数不为1,那么就会有无数种数目是凑不出的,比如最大公约数是3,那么选出n笼后的结果就一定是3的倍数,这样不是3的倍数的数字就凑不出了,最大公约数是一,那就成了一个背包问题用j表示容量,如果j-a[i]可以表示,那么j也可以表示
#include<bits/stdc++.h>
using namespace std;
int f[110*110];
int a[200];
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
int main(){
int n,num,ans=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
num=gcd(a[0],a[1]);
for(int i=2;i<n;i++){
num=gcd(a[i],num);
}
if(num!=1){
cout<<"INF"<<endl;
return 0;
}
f[0]=1;
for(int i=0;i<n;i++){
for(int j=a[i];j<=10001;j++){
if(f[j-a[i]]) f[j]=1;
}
}
for(int i=0;i<10001;i++){
if(!f[i]) ans++;
}
cout<<ans<<endl;
}