【算法提高——第二讲】搜索(3)

简介: 【算法提高——第二讲】搜索(3)

2.9.2 1117. 单词接龙

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=50;
string str[N],start;
int n;
bool st[N];
int ans;
bool judge(string s)
{
    for(int i=0;i<2*n;i++)
    {
        int _min=min(s.length(),str[i].length());
        for(int len=1;len<_min;len++)
        {
            if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
            {
                return true;
            }
        }
    }
    return false;
}
void dfs(string s)
{
    if(judge(s))
    {
        string tmp="";
        for(int i=0;i<2*n;i++)
        {
            int _min=min(s.length(),str[i].length());
            for(int len=1;len<_min;len++)
            {
                if(s.substr(s.length()-len)==str[i].substr(0,len)&&st[i]==false)
                {
                    st[i]=true;
                    tmp=s+str[i].substr(len);
                    dfs(tmp);
                    st[i]=false;
                }
            }
        }
    }
    else
    {
        ans=max(ans,(int)s.length());
        return;
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>str[i];
    for(int i=n;i<2*n;i++) str[i]=str[i-n];
    cin>>start;
    string s="#"+start;
    dfs(s);
    cout<<ans-1<<endl;
    return 0;
}

2.9.3 1118. 分成互质组

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=11;
int n;
int p[N];
int group[N][N];
bool st[N];
int ans=N;
//g:第几组;gc:当前组内下标是什么;
//tc:当前组中共有多少元素;start:当前组可以从哪个下标开始搜
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
bool check(int group[],int gc,int i)
{
    for(int j=0;j<gc;j++)
    {
        if(gcd(p[group[j]],p[i])>1)
            return false;
    }
    return true;
}
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(!st[i]&&check(group[g],gc,i))
        {
            st[i]=true;
            group[g][gc]=i;
            dfs(g,gc+1,tc+1,i+1);
            st[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;
    return 0;
}

2.10 DFS之剪枝与优化

2.10.1 165. 小猫爬山

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=25;
int n,w;
int cat[N];
int sum[N];
bool st[N];
int ans=N;
bool cmp(int a,int b)
{
    return a>b;
}
void dfs(int u,int k)
{
    if(k>=ans) return;
    if(u==n)
    {
        ans=k;
        return;
    }
    for(int i=0;i<k;i++)
    {
        if(cat[u]+sum[i]<=w)
        {
            sum[i]+=cat[u];
            dfs(u+1,k);
            sum[i]-=cat[u];
        }
    }
    sum[k]=cat[u];
    dfs(u+1,k+1);
    sum[k]=0;
}
int main()
{
    cin>>n>>w;
    for(int i=0;i<n;i++) cin>>cat[i];
    sort(cat,cat+n,cmp);
    dfs(0,0);
    cout<<ans;
    return 0;
}

2.10.2 166. 数独

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=9;
char str[100];
int ones[1<<N],mp[1<<N];
int row[N],col[N],cell[3][3];
inline int lowbit(int x)
{
    return x&-x;
}
void init()
{
    for(int i=0;i<N;i++)
    {
        row[i]=(1<<N)-1;
        col[i]=(1<<N)-1;
    }
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            cell[i][j]=(1<<N)-1;
        }
    }
}
inline int get(int x,int y)
{
    return row[x]&col[y]&cell[x/3][y/3];
}
bool bfs(int cnt)
{
    if(cnt==0) return true;
    int x,y,minv=10;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(str[i*N+j]=='.')
            {
                int t=ones[get(i,j)];
                if(t<minv)
                {
                    x=i,y=j,minv=t;
                }
            }
        }
    }
    int t=get(x,y);
    for(;t!=0;t-=lowbit(t))
    {
        int n=mp[lowbit(t)];
        row[x]-=1<<n;
        col[y]-=1<<n;
        cell[x/3][y/3]-=1<<n;
        str[x*N+y]='1'+n;
        if(bfs(cnt-1)) return true;
        row[x]+=1<<n;
        col[y]+=1<<n;
        cell[x/3][y/3]+=1<<n;
        str[x*N+y]='.';
    }
    return false;
}
int main()
{
    for(int i=0;i<N;i++) mp[1<<i]=i;
    for(int i=0;i<(1<<N);i++)
    {
        int s=0;
        for(int j=i;j;j-=lowbit(j)) s++;
        ones[i]=s;
    }
    while(true)
    {
        init();
        cin>>str;
        if(str[0]=='e')
            break;
        int cnt=0;
        for(int i=0,k=0;i<N;i++)
        {
            for(int j=0;j<N;j++,k++)
            {
                if(str[k]!='.')
                {
                    int t=str[k]-'1';
                    row[i]-=1<<t;
                    col[j]-=1<<t;
                    cell[i/3][j/3]-=1<<t;
                }
                else cnt++;
            }
        }
        bfs(cnt);
        cout<<str<<endl;
    }
    return 0;
}

2.10.3 167. 木棒

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=70;
int sticks[N];
bool st[N];
int n;
int sum,length;
bool dfs(int u,int cur,int start)
{
    if(u*length==sum) return true;
    if(cur==length) return dfs(u+1,0,0);
    for(int i=start;i<n;i++)
    {
        int l=sticks[i];
        if(st[i]||cur+l>length) continue;
        st[i]=true;
        if(dfs(u,cur+l,i+1)) return true;
        st[i]=false;
        if(!cur||cur+l==length) return false;
        int j=i;
        while(j<n&&sticks[j]==sticks[i]) j++;
        i=j-1;
    }
    return false;
}
int main()
{
    while(true)
    {
        fill(st,st+N,false);
        sum=0,length=0;
        cin>>n;
        if(n==0) break;
        for(int i=0;i<n;i++)
        {
            cin>>sticks[i];
            sum+=sticks[i];
            length=max(length,sticks[i]);
        }
        sort(sticks,sticks+n);
        reverse(sticks,sticks+n);
        while(length<=sum)
        {
            if(sum%length==0&&dfs(0,0,0))
            {
                cout<<length<<endl;
                break;
            }
            length++;
        }
    }
    return 0;
}

2.10.4 168. 生日蛋糕

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=25,INF=1e9;
int n,m;
int minv[N],mins[N];
int R[N],H[N];
int ans=INF;
void dfs(int u,int v,int s)
{
    if(v+minv[u]>n) return;
    if(s+mins[u]>=ans) return;
    if(s+2*(n-v)/R[u+1]>=ans) return;
    if(!u)
    {
        if(v==n) ans=s;
        return;
    }
    for(int r=min(R[u+1]-1,(int)sqrt(n-v));r>=u;r--)
    {
        for(int h=min(H[u+1]-1,(n-v)/r/r);h>=u;h--)
        {
            int t=0;
            if(u==m) t=r*r;
            R[u]=r,H[u]=h;
            dfs(u-1,v+r*r*h,s+2*r*h+t);
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        minv[i]=minv[i-1]+i*i*i;
        mins[i]=mins[i-1]+2*i*i;
    }
    R[m+1]=H[m+1]=INF;
    dfs(m,0,0);
    if(ans==INF) cout<<0<<endl;
    else cout<<ans<<endl;
    return 0;
}

2.11 迭代加深

2.11.1 170. 加成序列

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=110;
int n;
int path[N];
bool dfs(int u,int depth)
{
    if(u==depth) return path[u-1]==n;
    bool st[N]={false};
    for(int i=u-1;i>=0;i--)
    {
        for(int j=i;j>=0;j--)
        {
            int s=path[i]+path[j];
            if(s>path[u-1]&&s<=n&&!st[s])
            {
                st[s]=true;
                path[u]=s;
                if(dfs(u+1,depth)) return true;
            }
        }
    }
    return false;
}
int main()
{
    while(true)
    {
        cin>>n;
        if(n==0) break;
        int depth=1;
        path[0]=1;
        while(!dfs(1,depth)) depth++;
        for(int i=0;i<depth;i++)
        {
            cout<<path[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

2.12 双向DFS

2.12.1 171. 送礼物

image.png


代码:

#include<bits/stdc++.h>
using namespace std;
const int N=50;
typedef long long LL;
int n,m,k;
int g[N];
int weights[1<<24],cnt;
int ans;
void dfs_1(int u,int s)
{
    if(u==k)
    {
        weights[cnt++]=s;
        return;
    }
    if((LL)s+g[u]<=m) dfs_1(u+1,s+g[u]);
    dfs_1(u+1,s);
}
void dfs_2(int u,int s)
{
    if(u==n)
    {
        int l=0,r=cnt-1;
        while(l<r)
        {
            int mid=l+r+1>>1;
            if((LL)weights[mid]+s<=m) l=mid;
            else r=mid-1;
        }
        if(weights[r]+s<=m)
            ans=max(ans,weights[r]+s);
        return;
    }
    if((LL)s+g[u]<=m) dfs_2(u+1,s+g[u]);
    dfs_2(u+1,s);
}
int main()
{
    cin>>m>>n;
    for(int i=0;i<n;i++) cin>>g[i];
    sort(g,g+n);
    reverse(g,g+n);
    k=n/2+2;
    dfs_1(0,0);
    sort(weights,weights+cnt);
    cnt=unique(weights,weights+cnt)-weights;
    dfs_2(k,0);
    cout<<ans;
    return 0;
}

2.13 IDA*

2.13.1 180. 排书

image.png


代码:


#include<bits/stdc++.h>
using namespace std;
const int N=15;
int n;
int q[N];
int w[5][N];
int f()
{
    int tot=0;
    for(int i=0;i+1<n;i++)
    {
        if(q[i+1]!=q[i]+1)
            tot++;
    }
    return (tot+2)/3;
}
bool check()
{
    for(int i=0;i<n;i++)
    {
        if(q[i]!=i+1)
            return false;
    }
    return true;
}
bool dfs(int depth,int max_depth)
{
    if(depth+f()>max_depth) return false;
    if(check()) return true;
    for(int len=1;len<=n;len++)
    {
        for(int l=0;l+len-1<n;l++)
        {
            int r=l+len-1;
            for(int k=r+1;k<n;k++)
            {
                memcpy(w[depth],q,sizeof q);
                int x,y;
                for(x=r+1,y=l;x<=k;x++,y++)
                {
                    q[y]=w[depth][x];
                }
                for(x=l;x<=r;x++,y++)
                {
                    q[y]=w[depth][x];
                }
                if(dfs(depth+1,max_depth)) return true;
                memcpy(q,w[depth],sizeof q);
            }
        }
    }
    return false;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>q[i];
        int depth=0;
        while(depth<5&&!dfs(0,depth)) depth++;
        if(depth>=5) cout<<"5 or more"<<endl;
        else cout<<depth<<endl;
    }
    return 0;
}

2.13.2 181. 回转游戏

image.png


代码:

#include<bits/stdc++.h>
using namespace std;
const int N=24;
int op[8][7]={
    {0,2,6,11,15,20,22},
    {1,3,8,12,17,21,23},
    {10,9,8,7,6,5,4},
    {19,18,17,16,15,14,13},
    {23,21,17,12,8,3,1},
    {22,20,15,11,6,2,0},
    {13,14,15,16,17,18,19},
    {4,5,6,7,8,9,10}
};
int oppsite[8]={5,4,7,6,1,0,3,2};
int center[8]={6,7,8,11,12,15,16,17};
int q[N];
int path[100];
int sum[4];
int f()
{
    fill(sum,sum+4,0);
    for(int i=0;i<8;i++)
        sum[q[center[i]]]++;
    int k=0;
    for(int i=1;i<=3;i++)
    {
        k=max(k,sum[i]);
    }
    return 8-k;
}
void operate(int x)
{
    int t=q[op[x][0]];
    for(int i=1;i<7;i++)
    {
        q[op[x][i-1]]=q[op[x][i]];
    }
    q[op[x][6]]=t;
}
bool dfs(int depth,int max_depth,int last)
{
    if(depth+f()>max_depth) return false;
    if(f()==0) return true;
    for(int i=0;i<8;i++)
    {
        if(oppsite[i]==last) continue;
        operate(i);
        path[depth]=i;
        if(dfs(depth+1,max_depth,i)) return true;
        operate(oppsite[i]);
    }
    return false;
}
int main()
{
    while(scanf("%d",&q[0]),q[0])
    {
        for(int i=1;i<N;i++)
        {
            scanf("%d",&q[i]);
        }
        int depth=0;
        while(!dfs(0,depth,-1)) depth++;
        if(!depth)
            puts("No moves needed");
        else
        {
            for(int i=0;i<depth;i++)
            {
                printf("%c",path[i]+'A');
            }
            puts("");
        }
        printf("%d\n",q[6]);
    }
    return 0;
}

相关文章
|
2月前
|
算法 机器学习/深度学习 索引
【算法设计与分析】——搜索算法
【算法设计与分析】——搜索算法
40 1
|
2月前
|
算法 程序员 数据处理
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
算法与人生 揭秘C语言中高效搜索的秘诀——二分查找算法详解
|
4月前
|
算法 测试技术 C#
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
|
4月前
|
算法
【算法系列篇】递归、搜索和回溯(四)
【算法系列篇】递归、搜索和回溯(四)
|
4天前
|
算法
数据结构与算法-Trie树添加与搜索
数据结构与算法-Trie树添加与搜索
5 0
|
3月前
|
算法 测试技术 C++
【记忆化搜索】【剪枝】【C++算法】1553吃掉 N 个橘子的最少天数
【记忆化搜索】【剪枝】【C++算法】1553吃掉 N 个橘子的最少天数
|
3月前
|
算法 测试技术 C++
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
【动态规划】【记忆化搜索】【C++算法】664. 奇怪的打印机
|
3月前
|
移动开发 算法 测试技术
【动态规划】【记忆化搜索】C++算法:546移除盒子
【动态规划】【记忆化搜索】C++算法:546移除盒子
|
3月前
|
算法 Java C++
非启发式算法——二分、三分搜索算法
非启发式算法——二分、三分搜索算法
70 0
|
4月前
|
算法
【算法系列篇】递归、搜索和回溯(三)
【算法系列篇】递归、搜索和回溯(三)