穷竭搜索

DFS

POJ 1979: Red and Black
简单的DFS找四联通块即可。
代码如下

/*

*/
#define method_1
#ifdef method_1
/*

*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=20+5;
const int INF=0x3f3f3f3f;
const int dx[]={0,0,-1,1};
const int dy[]={1,-1,0,0};
int w,h,sx,sy,ans,vis[maxn][maxn]; //h为行数 w为列数 
char mp[maxn][maxn];
bool check(int x,int y){
    if(x<1||x>h||y<1||y>w||mp[x][y]=='#') return false;
    return true;
}
void init(){
    ans=0;
    memset(vis,0,sizeof(vis));
}
void dfs(int x,int y){
    vis[x][y]=1,ans++;
    for(int i=0;i<=3;i++){
        int newx=x+dx[i],newy=y+dy[i];
        if(check(newx,newy)&&!vis[newx][newy]){
            dfs(newx,newy);
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    //freopen("Red and Black.in","r",stdin);
    while(cin>>w>>h){
        init();
        if(w==0&&h==0) break;
        for(int i=1;i<=h;i++) for(int j=1;j<=w;j++) {
            cin>>mp[i][j];
            if(mp[i][j]=='@'){
            sx=i,sy=j;
            }
        }
        dfs(sx,sy);
        cout<

POJ 3009: Curling 2.0
冰球的移动规则较为复杂,但本质上是一个最短路问题。由于冰球会带来砖块破碎,所以需要用回溯法求解。因此BFS求解最短路尽管效率高,但回溯困难,所以采用了DFS求解。
代码如下

/*

*/
#define method_1
#ifdef method_1
/*

*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=20+5;
const int INF=0x3f3f3f3f;

int w,h;

int a[maxn][maxn];

int ans=INF;
void dfs(int deep,int sx,int sy,int tx,int ty) {
    if(deep>10) {
        return;
    }
    if(sx==tx&&sy==ty) {
        /*
        if(deep>=4){
            cout<<"......"<=1; i--) {
        if(a[sx-1][sy]==1) {
            break;
        }
        if(a[i][sy]==1) {
            j=i+1;
            f2=true;
            break;
        }
        if(a[i][sy]==3) {
            ans=min(ans,deep+1);
            return;
        }
    }
    if(f2) {
        a[j-1][sy]=0;
        dfs(deep+1,j,sy,tx,ty);
        a[j-1][sy]=1;
    }

    for(int i=sy; i<=h; i++) {
        if(a[sx][sy+1]==1) {
            break;
        }
        if(a[sx][i]==1) {
            j=i-1;
            f3=true;
            break;
        }
        if(a[sx][i]==3) {
            ans=min(ans,deep+1);
            return;
        }
    }
    if(f3) {
        a[sx][j+1]=0;
        dfs(deep+1,sx,j,tx,ty);
        a[sx][j+1]=1;
    }

    for(int i=sy; i>=1; i--) {
        if(a[sx][sy-1]==1) {
            break;
        }
        if(a[sx][i]==1) {
            j=i+1;
            f4=true;
            break;
        }
        if(a[sx][i]==3) {
            ans=min(ans,deep+1);
            return;
        }
    }
    if(f4) {
        a[sx][j-1]=0;
        dfs(deep+1,sx,j,tx,ty);
        a[sx][j-1]=1;
    }
    return;
}

int main() {
    ios::sync_with_stdio(false);
    //freopen("Curling 2.0.in","r",stdin);
    while(cin>>h>>w&&w!=0&&h!=0) {
        ans=INF;
        memset(a,0,sizeof(a));
        int sx,sy,tx,ty;
        for(int i=1; i<=w; i++) {
            for(int j=1; j<=h; j++) {
                cin>>a[i][j];
                if(a[i][j]==2) {
                    sx=i;
                    sy=j;
                }
                if(a[i][j]==3) {
                    tx=i;
                    ty=j;
                }
            }
        }
        /*
        for(int i=1; i<=w; i++) {
            for(int j=1; j<=h; j++) {
                cout<10) {
            cout<<"-1"<

BFS

POJ 3669: Meteor Shower
将所有陨石拓展一格,在所有格子上标注最早毁灭时间。
用三元组(x,y,t)表示状态,即当前位于(x,y)时间为t,bfs时保证t小于所在格子的最早毁灭时间。
如果某个各自的最早毁灭时间为无穷,则当前状态三元组的t即为所求。
本题还有很多实现细节,详见代码注释。
代码如下

/*

*/
#define method_1
#ifdef method_1
/*
将所有陨石拓展一格,在所有格子上标注最早毁灭时间
用三元组(x,y,t)表示状态,即当前位于(x,y)时间为t,bfs时保证t小于所在格子的最早毁灭时间
如果某个各自的最早毁灭时间为无穷,则当前状态三元组的t即为所求。 
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=300+5;
const int n=300;
const int INF=0x3f3f3f3f;
const int dx[]={0,0,-1,1};
const int dy[]={1,-1,0,0};
int m,die[maxn][maxn],vis[maxn][maxn];
struct node{
    int x,y,t;
};
queueq;
bool check(int x,int y){
    if(x<0||x>n+2||y<0||y>n+2) return false; //注意 不要写成x>n 因为可以移动到x>300的坐标 
    return true;
}
void init(){
    memset(die,INF,sizeof(die));
    cin>>m;
    int x,y,t;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>t;
        die[x][y]=min(die[x][y],t);
        for(int j=0;j<=3;j++){
            int newx=x+dx[j],newy=y+dy[j];
            if(check(newx,newy)) die[newx][newy]=min(die[newx][newy],t);
        }
    }
}
int bfs(){
    node st;st.x=0,st.y=0,st.t=0;
    q.push(st);
//  q.push((node){0,0,0}); //用这种写法 poj会CE 
    while(q.size()){
        node now=q.front();q.pop();
        if(die[now.x][now.y]==INF) return now.t;
        for(int i=0;i<=3;i++){
            int newx=now.x+dx[i],newy=now.y+dy[i];
            if(check(newx,newy)&&!vis[newx][newy]&&now.t+1

穷竭搜索

POJ 2718: Smallest Difference
首先,最优解的组合必然是两个位数最接近的数。
即假设有n个数,那么一个是n/2位数,一个是n-n/2位数。
因此暴力dfs枚举第一个集合的选则方式即C(n,n/2)。
然后对于每种情况,先将第一个集合里头的数字全部dfs出来,排序。
再dfs第二个集合里头的所有情况,再在第一个集合里头二分查找比较即可。
对于这个算法,题目有些地方需要特判,详见代码注释。
代码如下

/*

*/
#define method_1
#ifdef method_1
/*
首先,最优解的组合必然是两个位数最接近的数
即假设有n个数 那么一个是n/2位数 一个是n-n/2位数 
因此暴力dfs枚举第一个集合的选则方式即C(n,n/2)
然后对于每种情况,先将第一个集合里头的数字全部dfs出来,排序。
再dfs第二个集合里头的所有情况,再在第一个集合里头二分查找比较即可。 
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=10+5;
const int INF=0x3f3f3f3f;
int T,ans,n,a[maxn],vis[maxn];
vectorchoose[2],result;
void init(){
    ans=INF,n=0;
    memset(vis,0,sizeof(vis));
    choose[0].clear();choose[1].clear();
    result.clear();
}
void gen(){ //暴力枚举第一个集合能够组成的所有数字 
    result.clear();
    do{
        if(choose[0][0]==0) continue;
        int sum=0;
        for(int i=0;i=0)ans=min(ans,abs(result[pos]-sum)); //注意这里必须用if判断是否越界
    if(pos-1=0)ans=min(ans,abs(result[pos-1]-sum));
    /* 
    if(ans==0){
        cout<n) return; 
    if(m+n-p+1>T;
    getchar(); //忽略第一个换行 
    while(T--){
        init();
        char ch;
        while((ch=getchar())!='\n'){
            if(ch=='\n') break;
            else if(isdigit(ch)) a[++n]=ch-'0';
        }
//      for(int i=1;i<=n;i++) cout<

POJ 3187: Backward Digit Sums
next_permutation这么快的吗。
看到n<=10就放弃了使用全排列。
想从终态开始搜索然后剪枝。
结果去看题解发现就是枚举初态全排列然后判断即可。理论复杂度是O(n!1010)
没想到竟然能AC。
代码如下
(PS:method_1结果为TLE,method_2注意特判1 1这组数据

/*
next_permutation这么快的吗
看到n<=10就放弃了使用全排列
想从终态开始搜索然后剪枝
结果去看题解发现就是枚举初态全排列然后判断即可 理论复杂度是O(n!*10*10)没想到竟然能AC 
*/
#define method_2
#ifdef method_1
/*
从终态开始搜索然后剪枝
TLE
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=10+5;
const int INF=0x3f3f3f3f;
int n,sum,a[maxn];
sets;
void dfs(int dep,int b[]){ //目前搜索深度为dep 分解情况为数组b 
    if(dep==0){
        bool f=true;s.clear();
        for(int i=1;i<=n;i++){
            if(s.count(b[i])==0&&b[i]>=1&&b[i]<=n) s.insert(b[i]);
            else f=false;
        }
        if(f){
            for(int i=1;i<=n;i++) cout<>n>>sum;
    a[1]=sum;
    dfs(n-1,a);
    return 0;
}
#endif
#ifdef method_2
/*
188ms
AC
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=10+5;
const int INF=0x3f3f3f3f;
int n,sum,a[maxn],b[maxn],c[maxn];
bool check(){
    memcpy(c,a,sizeof(a)); //备份a数组 
    for(int i=2;i<=n;i++){
        for(int j=1;j<=n-i+1;j++){
            b[j]=a[j]+a[j+1];
//          cout<>n>>sum;
    if(n==1){ //需要特判 
        cout<<1;
        return 0;
    }
    for(int i=1;i<=n;i++) a[i]=i;
    do{
//      for(int i=1;i<=n;i++) cout<

POJ 3050: Hopscotch
爆搜即可,map判重,注意poj上map套string要加头文件 #include
代码如下

/*

*/
#define method_1
#ifdef method_1
/*
爆搜即可
map判重 
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define D(x) cout<<#x<<" = "<pii;
const int maxn=5+5;
const int n=5;
const int INF=0x3f3f3f3f;
const int dx[]={0,0,-1,1};
const int dy[]={1,-1,0,0};
int a[maxn][maxn],ans=0;
mapmp; //poj上map套string要加头文件 #include
bool check(int x,int y){
    if(x<1||x>n||y<1||y>n) return false;
    return true;
}
void dfs(int x,int y,string s){
    s+=char(a[x][y]+'0');
    if(s.length()==6){
        if(mp[s]==0) mp[s]=++ans;
        return;
    }
    for(int i=0;i<=3;i++){
        int newx=x+dx[i],newy=y+dy[i];
        if(check(newx,newy)) dfs(newx,newy,s);
    }
}
int main() {
    ios::sync_with_stdio(false);
    //freopen("Hopscotch.in","r",stdin);
    for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) cin>>a[i][j];
    for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) dfs(i,j,"");
    cout<

你可能感兴趣的:(穷竭搜索)