規律,模擬,貪心(Travelling Salesman Problem,HDU 5402)

顯然行列有一個是奇數就可以全部走完。這種情況直接模擬就好。

否則的話,一定會有一個格子走不到。

多試幾種情況就可以發現這個規律。

證明的話:http://blog.csdn.net/queuelovestack/article/details/47756605

就是對整個棋盤進行黑白二染色,如果行列相加爲偶數,就染成黑色,否則染成白色。我們的路徑一定是黑白相間。

當行列皆爲偶數的時候我們可以發現矛盾。

此時(1,1)是黑色,(n,m)也是黑色。因爲路徑黑白相間,所以經過的白色格子一定比黑色格子少一個。而整個棋盤中黑白格子的個數是相等的,所以至少有1個白色格子是走不到的。

比賽時不一定能想到嚴格證明,但若能發現規律,並且有一定把握也是可以的。

至於該如何模擬,看到了網上有很簡單的辦法,就是隨便繞繞就繞過去了,我的模擬就麻煩很多了。

如果可以,儘量想出一些簡單的模擬辦法,當然能想到自己的辦法是好事,但這可能會給編程帶來一些麻煩。

希望自己在找到線索之後可以進一步地把它想清楚,從而找到更簡單的規律,然後再開始編程。


代碼

#include<stdio.h>
#include<vector>
using namespace std;
const int maxn = 110;

int n,m;
int MAP[maxn][maxn];
int mr,mc;
vector<char>vec;
int ans;
int vis[maxn][maxn];

void read()
{
    ans=0;
    vec.clear();
    mr=mc=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            vis[i][j]=0;
            scanf("%d",&MAP[i][j]);
            if(!(i==1&&j==1)&&!(i==n&&j==m)&&((i+j)&1)&&MAP[mr][mc]>MAP[i][j])
            {
                mr=i;
                mc=j;
            }
        }
}

bool ok(int r,int c)
{
    return 1<=r&&r<=n&&1<=c&&c<=m&&!(r==mr&&c==mc)&&!vis[r][c];
}

int change(int r,int c,int t)
{
    if(t==0)
    {
        if(c==m) return 1;
        for(int i=1;i<=n;i++)
            if(ok(i,c+1)&&!vis[i][c+1]) return 0;
        return 1;
    }
    if(t==1)
    {
        if(c==1) return n-r<=m-c?2:0;
        for(int i=1;i<=n;i++)
            if(ok(i,c-1)&&!vis[i][c-1]) return 1;
        return n-r<=m-c?2:0;
    }
    if(t==2)
    {
        if(r==n) return 3;
        for(int i=1;i<=m;i++)
            if(ok(r+1,i)&&!vis[r+1][i]) return 2;
        return 3;
    }
    if(t==3)
    {
        if(r==1) return n-r<m-c?2:0;;
        for(int i=1;i<=m;i++)
            if(ok(r-1,i)&&!vis[r-1][i]) return 3;
        return n-r<m-c?2:0;
    }
    return 0;
}

void dfs(int r,int c,int t)
{
    ans+=MAP[r][c];
    vis[r][c]=1;
    if(r==n&&c==m) return;
    t=change(r,c,t);
    if(t==0)
    {
        if(ok(r-1,c))
        {
            vec.push_back('U');
            dfs(r-1,c,t);
        }
        else if(ok(r,c+1))
        {
            vec.push_back('R');
            dfs(r,c+1,t);
        }
        else if(ok(r+1,c))
        {
            vec.push_back('D');
            dfs(r+1,c,t);
        }
        return;
    }
    else if(t==1)
    {
        if(ok(r-1,c))
        {
            vec.push_back('U');
            dfs(r-1,c,t);
        }
        else if(ok(r,c-1))
        {
            vec.push_back('L');
            dfs(r,c-1,t);
        }
        else if(ok(r+1,c))
        {
            vec.push_back('D');
            dfs(r+1,c,t);
        }
        return;
    }
    else if(t==2)
    {
        if(ok(r,c-1))
        {
            vec.push_back('L');
            dfs(r,c-1,t);
        }
        else if(ok(r+1,c))
        {
            vec.push_back('D');
            dfs(r+1,c,t);
        }
        else if(ok(r,c+1))
        {
            vec.push_back('R');
            dfs(r,c+1,t);
        }
        return;
    }
    else if(t==3)
    {
        if(ok(r,c-1))
        {
            vec.push_back('L');
            dfs(r,c-1,t);
        }
        else if(ok(r-1,c))
        {
            vec.push_back('U');
            dfs(r-1,c,t);
        }
        else if(ok(r,c+1))
        {
            vec.push_back('R');
            dfs(r,c+1,t);
        }
        return;
    }
}

void handle()
{
    if(n>=m) dfs(1,1,0);
    else dfs(1,1,2);
}

void solve()
{
    read();
    if((n&1)==0&&(m&1)==0);
    else mr=mc=0;
    handle();
    printf("%d\n",ans);
    for(int i=0;i<(int)vec.size();i++)
        printf("%c",vec[i]);
    puts("");
}

int main()
{
    MAP[0][0]=10010;
    while(~scanf("%d %d",&n,&m)) solve();
    return 0;
}


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