實驗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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章