首页 > 代码库 > ACM 暴力搜索题 题目整理

ACM 暴力搜索题 题目整理

UVa 129 Krypton Factor

注意输出格式,比较坑爹。

每次要进行处理去掉容易的串,统计困难串的个数。

#include<iostream>#include<vector>#include<cmath>#include<map>#include<algorithm>#include<cstring>#include<cstdio>#include<cstdlib>#include<string>#define INF 1000000000LL#define ll long longusing namespace std;char str[100];int cnt,K,L;bool check(int len){    int l=strlen(str);    if(l==0||l==1) return false;    for(int i=1; i<=len/2; ++i)    {        bool ok=true;        for(int j=0; j<i&&ok; ++j)        {            if(str[len-1-j]!=str[len-1-i-j])                ok=false;        }        if(ok) return true;    }    return false;}void dfs(int pos){    if(cnt>=K) return ;    else    {        for(int i=0; i<L; ++i)        {            str[pos]=A+i;            str[pos+1]=0;            if(!check(pos+1)) cnt++;            else continue ;            dfs(pos+1);            if(cnt>=K) return ;        }    }}int main(){    while(scanf("%d%d",&K,&L)!=EOF)    {        if(!K&&!L) break;        cnt=0;        dfs(0);        int L=strlen(str);        for(int i=0; str[i]; ++i)        {            if(i&&i%4==0&&i%64) putchar( );            putchar(str[i]);            if((i+1)%64==0) putchar(\n);        }        if(L%64) putchar(\n);        printf("%d\n",L);    }    return 0;}
View Code

 

SPOJ COMCB  1003

注意棋盘方格总数不会超过26。所以可以尝试dfs回溯寻找最优解。

怎么找字典序最小的,这个把棋盘画出来,然后指定一下每次跳的方向的顺序就行。如果第一个跳完全部棋盘的就是最优解。

这里要求输出最优解,每个位置是二维的,可以把它们压缩成一维,开一个数组,下标存第几步,内容存位置,这样就方便储存了。

实际上可行解并不多,可以打表。

 

View Code

 

HDU 4848 Wow! Such Conquering!

首先用fylod求最短路,然后搜索。时间复杂度大约是30!。肯定要剪枝。

有两个剪枝,一个是如果当前时刻有星球永远无法到达,则return,另一个是如果到该星球以后的时间花费比当前最优解要小则剪枝。这样就能过了。

#include <iostream>#include <string>#include <cstdio>#include <cstring>#include <algorithm>#define inf 100000000using namespace std;int dist[35][35],tim[35];int n;int ans;bool vis[35];void dfs(int now,int rest,int all,int sum){    if(all>=ans) return ;    if(rest==0)    {        ans=min(ans,all);        return ;    }    for(int i=1; i<n; ++i)        if((!vis[i])&&(sum+dist[now][i]>tim[i]))            return;    for(int i=1; i<n; ++i)    {        if(!vis[i])        {            int time=sum+dist[now][i];            if(time<=tim[i])            {                if(ans<=all+rest*time) continue;                vis[i]=true;                dfs(i,rest-1,all+time,time);                vis[i]=false;            }        }    }}int main(){    while(scanf("%d",&n)!=EOF)    {        for(int i=0; i<n; ++i)            for(int j=0; j<n; ++j)            {                scanf("%d",&dist[i][j]);            }        for(int k=0; k<n; ++k)            for(int i=0; i<n; ++i)                for(int j=0; j<n; ++j)                    dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);        for(int i=1; i<n; ++i)        {            scanf("%d",&tim[i]);        }        ans=inf;        memset(vis,0,sizeof(vis));        vis[0]=true;        dfs(0,n-1,0,0);        if(ans==inf) puts("-1");        else printf("%d\n",ans);    }    return 0;}
View Code

 

 SGU 125  Shtirlits

给一个矩阵B,每个元素B[i][j]表示A[i][j]上下左右四周有多少个数大于自身。输出一个可能的矩阵A。

由于n<=3,完全可以暴力搜索解决。但是9^9肯定会超时的,考虑剪枝。对于每个A[i][j]枚举可能的元素,当枚举到第二行以上的时候,该元素上面的一个元素四周的元素都已经确定了,可以判断是否满足题意,不满足则剪枝。当枚举到最后一行的时候,还可以判断左边的元素是否满足题意。当所有元素都枚举完毕,要进行一次全体的判断,如果符合就是答案。

之前想到一个剪枝,以为每次枚举A[i][j],可以从0枚举到9-B[i][j]。其实这是不对的,因为比A[i][j]大的元素可能是相同的。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int B[4][4];int A[4][4];int n;bool judge(int x,int y){    return 0<=x&&x<n&&0<=y&&y<n;}const int Move[4][2]= {{-1,0},{0,-1},{1,0},{0,1}};bool check(int x,int y){    int cnt=0;    for(int i=0; i<4; ++i)    {        int nx=x+Move[i][0],ny=y+Move[i][1];        if(judge(nx,ny))        {            if(A[x][y]<A[nx][ny])                cnt++;        }    }    return cnt==B[x][y];}bool dfs(int cur){    if(cur==n*n)    {         for(int i=0;i<n;++i)            for(int j=0;j<n;++j)            if(!check(i,j)) return false;         return true;    }    const int x=cur/n,y=cur%n;    for(int i=0; i<=9; ++i)    {        A[x][y]=i;        if((x>=1&&!check(x-1,y))||(x==n-1&&y>=1&&!check(x,y-1)))            continue;        if(dfs(cur+1))            return true;    }    return false;}int main(){    while(scanf("%d",&n)!=EOF)    {        for(int i=0; i<n; ++i)            for(int j=0; j<n; ++j)                scanf("%d",&B[i][j]);        if(!dfs(0))            puts("NO SOLUTION");        else        {            for(int i=0; i<n; ++i)            {                for(int j=0; j<n; ++j)                    if(!j) printf("%d",A[i][j]);                    else printf(" %d",A[i][j]);                printf("\n");            }        }    }    return 0;}
View Code