实验9 回溯法实验一

实验9 回溯法实验一

OJ练习
1. 畅通工程续:http://acm.hdu.edu.cn/showproblem.php?pid=1874
2. 最短路径问题:http://acm.hdu.edu.cn/showproblem.php?pid=3790
3. 最短路:http://acm.hdu.edu.cn/showproblem.php?pid=2544
4*. Choose the best route:http://acm.hdu.edu.cn/showproblem.php?pid=2680
5*. 一个人的旅行:http://acm.hdu.edu.cn/showproblem.php?pid=2066
6*. HDU Today:http://acm.hdu.edu.cn/showproblem.php?pid=2112
7*. Bus System:http://acm.hdu.edu.cn/showproblem.php?pid=1690
8*. 0 or 1:http://acm.hdu.edu.cn/showproblem.php?pid=4370

实验内容
1. 编程实现Dijkstra算法。
输入:第1行第1个值表示顶点个数,第2个值表示边个数;第2行开始为边及权重。例:
5 7 0
0 1 10
0 3 30
0 4 100
1 2 50
2 4 10
3 2 20
3 4 60
输出:顶点0到每一个顶点的最短路径长度。例:
0 10 50 30 60
源代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 10010;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
struct node
{
    int to,cost;
    node(int t,int c):to(t),cost(c){}
    bool operator < (const node & a)const {
        return cost > a.cost;
    }
};
vector<node> E[maxn];
ll d[maxn];
priority_queue<pli,vector<pli>,greater<pli> > Q;

int main()
{

    int n,m,st;
    cin>> n>>m>>st;
    for(int i=1;i<=m;i++)
    {
        int x,y,v;
        scanf("%d %d %d",&x, &y ,&v);
        E[x].push_back({y,v});
    }
    for(int i=1;i<=n;i++)
    {
        d[i]=INF;
    }
    d[st] = 0;
    Q.push({0,st});
    while ( Q.size() )
    {
        pli now = Q.top();Q.pop();
        ll cost = now.first;
        int p=now.second;
        if(cost >= INF)
            continue;
        for(int i=0;i<E[p].size();i++)
        {
            int v = E[p][i].to;
            if(d[v] > cost + E[p][i].cost)
            {
                d[v] = cost + E[p][i].cost;
                Q.push({d[v],v});
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        if(i!= n-1)
            cout<<d[i]<<" ";
        else
            cout<<d[i];
    }
    cout<<endl;

}
  1. 用1, 2, 3…9 这九个数字组成一个数学公式,满足:ABC + DEF = GHI,每个数字只能出现一次,编写程序输出所有的组合。
    源代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 10010;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
int a[10],book[10];
void dfs(int step)
{
  if(step == 10)
  {
        int i;
        int t=(a[1]*100+a[2]*10+a[3]);
        int k=(a[7]*100+a[8]*10+a[9]);
        int g=(a[4]*100+a[5]*10+a[6]);

        if(t*3==k&&t*2==g && (t!=0))
        {
            for(i=1;i<10;i++)
            {
                printf("%d",a[i]);
                if(i%3==0)  printf(" ");
            }
            printf("\n");
            return ;
        }
    }
    for(int i=1;i<10;i++)
    {
        if(book[i]==0)
        {
            a[step] = i;
            book[i] = 1;
            dfs(step+1);
            book[i] = 0;
        }

    }
    return ;
}
int main()
{
   dfs(1);
   return 0;
}
  1. 使用回溯法求解N后问题。

输入:皇后的个数。输入示例:
4
输出:每一种方案及总方案数。输出示例:
0 1 0 0
0 0 0 2
3 0 0 0

0 0 4 0

0 0 1 0
2 0 0 0
0 0 0 3

0 4 0 0

总方案数为2。
源代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
char a[maxn][maxn];
int m,n,b[maxn][maxn];
int x[maxn];

int place(int k)
{
    int i=1;
    while(i < k)
    {
        if((x[i]==x[k]) || (abs(x[i]-x[k])==abs(i-k))) return 0;
        i++;
    }
    return 1;
}
void print(int x[],int n)
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
            if(x[i]==j)  printf(" %d ",i);
            else  printf(" 0 ");
        printf("\n");
    }
    printf("\n");
}
void nqueue(int n){
    int k=1,total=0;
    x[k]=0;
    while(k>0)
    {
        x[k]++;
        while(k<=n && !place(k))
        {
            x[k]++;
        }
        if(x[k]<=n)
        {
            if(k==n)
            {
                print(x,n);
                total++;
            }
            else
            {
                k++;
                x[k]=0;
            }
        }
        else
        {
            k--;
        }
    }
    printf("%d\n",total);
}
int main()
{
    int n;
    scanf("%d",&n);
    nqueue(n);
}


4. 油田问题

输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块。如果两个字符“@”所在的格子相邻(横、竖或者对角线方向),即属于同一个八连块。例如,下图有两个八连块。

源代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
char a[maxn][maxn];
int m,n,b[maxn][maxn];
void dfs(int x,int y,int ans)
{
    if(x<0||x>=m||y<0||y>=n) return;
    if(b[x][y]>0||a[x][y]=='*') return;
    b[x][y]=ans;
    for(int k=-1;k<=1;k++)
        for(int t=-1;t<=1;t++)
            if(k!=0||t!=0)
                dfs(x+k,y+t,ans);
}
int main()
{
    int i,j;
    scanf("%d%d",&m,&n);
    int cnt=0;
    memset(b,0,sizeof(b));
    for(i=0;i<m;i++)
        scanf("%s",a[i]);
    for(i=0;i<m;i++)
        for(j=0;j<n;j++)
            if(b[i][j]==0&&a[i][j]=='@')
                dfs(i,j,++cnt);
    printf("%d\n",cnt);

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章