【個人訓練】(POJ3279)Fliptile

SamHX發表於2017-10-01

最近在刷kuangbin神犇的各種套題。。。。感覺自己好弱啊。。。。。還是要多多訓練,跟上大神的腳步。最近的這十幾題都比較水,記下來這一條我比較印象深刻、也比較難的題目吧(之後應該不會再有水題寫了,珍惜水題啊QAQ)

思考

題目其實很簡單,踩黑白啊,而且規模也不算大。問題在於我們怎麼窮舉。注意到一個問題,我們對單行中先後變換的次序其實不改變最後的結果。也就是說,對於單列的變換,其實我們可以純粹的只考慮上下帶來的影響。而又注意到每行實際上隻影響上下單行,所以我們可以規定一個處理的方向(如從上而下),那麼我們每次只需要考慮最新的一行對上面一行帶來的影響了。需要注意的是,這種思想我們之後估計會經常用到。(不過本菜狗估計還是做不對emmmmm
這題就是這個思路。窮舉第一行的踩踏方式,那麼會產生有黑有白。對上一行的黑,只能有此列的下一行來處理,因此我們逐行處理就行了。最後看最後一行合不合法即可。儲存最小資料。

程式碼

#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
using namespace std;

int maze[18][18],step[18][18];
int dx[]={0,-1,1,0,0};
int dy[]={0,0,0,-1,1};
int m,n;
int judge(int val)
{
    int tmpmaze[18][18];
    memcpy(tmpmaze,maze,sizeof(maze));
    int cnt=0;
    memset(step,0,sizeof(step));
    for(int i=1;i<=m;++i)
    {
        if(i==1) for(int j=1;j<=n;++j)
        {
            if((val>>(n-j))&1)
            {
                step[i][j]++;cnt++;
                for(int k=0;k!=5;++k)
                {
                    int tx=i+dx[k],ty=j+dy[k];
                    if(tx>=1 && tx<=m && ty>=1 && ty<=n)
                        tmpmaze[tx][ty]^=1;
                }
            }
        }
        else for(int j=n;j>=1;--j)
        {
            if(tmpmaze[i-1][j])
            {
                step[i][j]++;cnt++;
                for(int k=0;k!=5;++k)
                {
                    int tx=i+dx[k],ty=j+dy[k];
                    if(tx>=1 && tx<=m && ty>=1 && ty<=n)
                        tmpmaze[tx][ty]^=1;
                }
            }
        }
    }
    for(int i=1;i<=n;++i) if(tmpmaze[m][i]) return -1;
    return cnt;
}
int main()
{
    while(cin>>m>>n)
    {
        for(int i=1;i<=m;++i)
            for(int j=1;j<=n;++j)
                cin>>maze[i][j];
        int minans=0x3f3f3f3f,minstep[18][18];
        memset(minstep,0,sizeof(minstep));
        for(int i=0;i!=(1<<n);++i)
        {
            int ans=judge(i);
            if(ans!=-1 && minans>ans)
            {
                memcpy(minstep,step,sizeof(step));
                minans=ans;
            }
        }
        if(minans==0x3f3f3f3f)
            cout<<"IMPOSSIBLE"<<endl;
        else for(int i=1;i<=m;++i)
        {
            for(int j=1;j<=n;++j)
                cout<<minstep[i][j]<<" ";
            cout<<endl;
        }
    }   
    return 0;
}

相關文章