DFS题目及简析【持续刷题,更新中】

2018.4.20

UVA572 油田 看了刘汝佳老师的紫皮书上的例题,应该是用了一种叫做洪水填充或者种子填充的算法

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[101][101];
int visit[101][101];
int m,n;

void dfs(int r,int c,int cnt)
{
    if(r<0 || r >= m || c < 0 || c >= n)return;//超出范围限制
    if(visit[r][c] > 0 || s[r][c] != '@')return;//已经访问过或者不是@
    visit[r][c] = cnt;
    for(int dr = -1; dr <= 1; dr ++)
        for(int dc = -1; dc <= 1; dc ++)
        if(dc!=0||dr!=0)dfs(r+dr,c+dc,cnt);
}

int main()
{

    while(scanf("%d%d",&m,&n) && m && n)
    {

        for(int i = 0; i < m; i ++)
        {
            getchar();
            for(int j = 0; j < n; j ++)
            {
                scanf("%c",&s[i][j]);
            }
        }
        memset(visit,0,sizeof(visit));
        int cnt = 0;
        for(int i = 0; i < m; i ++)
            for(int j = 0; j < n; j ++)
                if(s[i][j] == '@'&&visit[i][j] == 0)dfs(i,j,++cnt);
        cout << cnt << endl;
    }
    return 0;
}

4.21

HDU1455 sticks 用了剪枝的思想

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100;
int a[maxn],v[maxn];
int p;//判断是否计算出最小值
int m;//输入的木棍个数m

int cmp(int i,int j)
{
    return i>j;
}
void dfs(int beg, int len, int aim, int num)//起始下标,木棍长度,目标长度,拼接的木棍总数
{
    if(p)return;
    if(num == m){
        p = 1;
        return;
    }
    for(int i = beg; i < m; i ++)
    {
        if(a[i] + len <= aim && v[i] != 1)
        {
            v[i] = 1;
            if(a[i]+len == aim)dfs(0,0,aim,num+1);
            else{
                dfs(i + 1, a[i] + len, aim, num+1);//这是个用num++就超时用++num就WA的地方
            }
            v[i] = 0;
            if(p) return;//完成,返回
            if(len == 0)return;//剪枝,如果前面的不满足条件,那么后面的也一定不满足
            while(i < m && a[i+1] == a[i]) ++i;//剪枝,若不满足条件,则把不满足条件的长度相等的木棍跳过去
        }
    }
}

int main()
{
    int sum;//所有木棍的总长度
    while(cin >> m && m!= 0)
    {
        memset(v,0,sizeof(v));
        sum = 0;
        for(int i = 0; i < m; i ++)
        {
            cin >> a[i];
            sum += a[i];
        }
        sort(a,a+m,cmp);
        for(int i = a[0]; i <= sum; i ++)
        {
            if(i == sum)cout << sum << endl;//如果只有一个木棍,直接输出
            else if(sum % i == 0)//剪枝
            {
                p = 0;
                dfs(0,0,i,0);
                if(p)
                {
                    cout << i << endl;
                    break;
                }
            }
        }
    }
    return 0;
}

4.23

HDU2553 N皇后问题 无论如何都超时,一气之下打了表

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;

int tot,n;
int v[20][20];

void searchs(int r)
{
    if(r >= n)
    {
         tot ++;
         return;
    }
    for(int i = 0; i < n; i ++)
    {
        if(!v[0][i]&&!v[1][r+i]&&!v[2][r-i+n])
        {
            v[0][i] = v[1][r+i] = v[2][r-i+n] = 1;
            searchs(r+1);
            v[0][i] = v[1][r+i] = v[2][r-i+n] = 0;
        }
    }
}

int main()
{
    while(scanf("%d",&n)&&n)
    {
//        clock_t start,ends;
//        start = clock();
        tot = 0;
        memset(v,0,sizeof(v));
        searchs(0);
        printf("%d\n",tot);
//        ends = clock();
//        printf("time:%d\n",ends - start);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值