poj 2870 Light Up (dfs+強剪枝)

來源:互聯網
上載者:User
Light Up
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 737   Accepted: 285

Description

Light Up is a puzzle set in a rectangular board divided in smaller squares. Some squares in the board are ``empty'' (white squares the figure below), some squares are ``barriers'' (dark squares in the figure below). A barrier square may have an integer number
i associated to it (0 <= i <= 4). 

 
Figure 2: (a) Puzzle with 6 rows, 7 columns and 7 barriers; (b) a solution to the puzzle.

In this puzzle the goal is to ``light up'' all the empty squares by placing lamps in some of them (lamps are depicted as circles in the figure). Each lamp illuminates the square it is on, plus all squares in line with it, horizontally or vertically, up to a
barrier square or the board end. 

A winning configuration satisfies the following conditions:

  • all empty squares must be lit;
  • no lamp may be lit by another lamp;
  • all numbered barrier squares must have exactly that number of lamps adjacent to them (in the four squares above, below, and to the side);
  • non-numbered barrier squares may have any number of lamps adjacent to them.

You must write a program to determine the smallest number of lamps that are needed to reach a winning configuration.

Input

The input contains several test cases. The first line of a test case contains two integers N, M indicating respectively the number of rows and the number of columns of the board (1 <= N <= 7, 1 <= M <= 7). The second line contains one integer B indicating the
number of barrier squares (0 <= B <= N × M). Each of the next B lines describe a barrier, containing three integers R, C and K, representing respectively the row number (1 <= R <= N), the column number (1 <= C <= M) and the barrier number (-1 <= K <= 4); K
= -1 means the barrier is unnumbered. The end of input is indicated by N = M = 0.

Output

For each test case in the input your program must produce one line of output, containing either an integer indicating the smallest number of lamps needed to reach a winning configuration, in case such a configuration exists, or the words `No solution'.

Sample Input

2 202 212 2 16 772 3 -13 3 04 2 15 4 35 6 21 7 -16 5 -10 0

Sample Output

2No solution8

題意:很簡單 不說了 如果要做這題 連題意都看不懂的話  就好好去學英語吧

思路:dfs+剪枝  地圖不大 將所有情況搜尋都搜一遍 最後判斷是否滿足條件 然後更新ans
不過這題剪枝還是必須的  具體代碼解釋的詳細 這裡不說了

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#define maxn 10using namespace std;int n,m,b,ans;int mp[maxn][maxn];int vis[maxn][maxn];int jmp[maxn][maxn];int light[maxn][maxn];int dx[]= {-1,1,0,0};int dy[]= {0,0,-1,1};void showvis()             // 中間輸出  方便debug{    int i,j;    printf("\n");    for(i=1; i<=n; i++)    {        for(j=1; j<=m; j++)        {            printf("%d",vis[i][j]);        }        printf("\n");    }}bool isok(int tx,int ty)  // 判斷能否放燈{    int i,j;    for(i=tx-1; i>=1; i--)    {        if(vis[i][ty]) return false;        else if(mp[i][ty]) break ;    }    for(i=tx+1; i<=n; i++)    {        if(vis[i][ty]) return false;        else if(mp[i][ty]) break ;    }    for(j=ty-1; j>=1; j--)    {        if(vis[tx][j]) return false;        else if(mp[tx][j]) break ;    }    for(j=ty+1; j<=m; j++)    {        if(vis[tx][j]) return false;        else if(mp[tx][j]) break ;    }    return true ;}void expand(int tx,int ty)     // 擴充  將燈能照亮的地方都點亮{    int i,j;    for(i=tx; i>=1; i--)    {        if(mp[i][ty]) break ;        else jmp[i][ty]=1;    }    for(i=tx; i<=n; i++)    {        if(mp[i][ty]) break ;        else jmp[i][ty]=1;    }    for(j=ty-1; j>=1; j--)    {        if(mp[tx][j]) break ;        else jmp[tx][j]=1;    }    for(j=ty+1; j<=m; j++)    {        if(mp[tx][j]) break ;        else jmp[tx][j]=1;    }}bool judge()                 // 判斷搜出來的情況是否合理{    int i,j,k,cnt;    memset(jmp,0,sizeof(jmp));    for(i=1; i<=n; i++)    {        for(j=1; j<=m; j++)        {            if(vis[i][j]) expand(i,j);        // 將標記了的都擴充        }    }    for(i=1; i<=n; i++)    {        for(j=1; j<=m; j++)        {            if(!mp[i][j]&&!jmp[i][j]) return false ;      // 如果還有一個位置沒亮的話就不行        }    }//    showvis();    for(i=1; i<=n; i++)              // 檢測牆的周圍燈的個數是否滿足條件    {        for(j=1; j<=m; j++)        {            if(light[i][j]==-1) continue ;            cnt=0;            for(k=0; k<4; k++)            {                if(vis[i+dx[k]][j+dy[k]]) cnt++;            }            if(cnt!=light[i][j]) return false ;        }    }    return true ;}bool midcut(int tx,int ty)        // 中間剪枝  如果有牆的周圍不滿足條件了 就 return false{    int i,j,k,cnt;    for(i=1; i<=tx-2; i++)    {        for(j=1; j<=m; j++)        {            if(light[i][j]==-1) continue ;            cnt=0;            for(k=0; k<4; k++)            {                if(vis[i+dx[k]][j+dy[k]]) cnt++;            }            if(cnt!=light[i][j]) return false ;        }    }    i=tx-1;    for(j=1; j<=ty-1; j++)    {        if(light[i][j]==-1) continue ;        cnt=0;        for(k=0; k<4; k++)        {            if(vis[i+dx[k]][j+dy[k]]) cnt++;        }        if(cnt!=light[i][j]) return false ;    }    return true ;}bool goodcut(int tx,int ty)     // 強剪枝   如果所搜點為牆 且其上方為黑暗的,則剪枝!{    int i,j,k,cnt;    memset(jmp,0,sizeof(jmp));    for(i=1; i<=tx-1; i++)    {        for(j=1; j<=m; j++)        {            if(vis[i][j]) expand(i,j);        }    }    if(!jmp[tx-1][ty]) return false;    return true ;}void dfs(int nx,int ny,int cxx){    if(ans<=cxx) return ;    if(!midcut(nx,ny)) return ;   // 中間剪枝可以不要 其實在poj上不要還快一些 因為他的資料沒有偏重這一點    if(nx>=n&&ny>m||nx>n)    {        if(judge())               // 全部搜完後判斷情況是否合理        {            if(ans>cxx) ans=cxx;  // 更新ans        }        return ;    }    if(ny>m) dfs(nx+1,1,cxx);    else if(mp[nx][ny])    {        if(nx>=2&&!mp[nx-1][ny]&&!goodcut(nx,ny)) return ;   // 注意前面的條件        dfs(nx,ny+1,cxx);    }    else    {        dfs(nx,ny+1,cxx);        if(!vis[nx][ny]&&isok(nx,ny))        {            vis[nx][ny]=1;            dfs(nx,ny+1,cxx+1);            vis[nx][ny]=0;        }    }}int main(){    int i,j,r,c,k;    while(scanf("%d%d",&n,&m),n||m)    {        scanf("%d",&b);        memset(mp,0,sizeof(mp));        memset(light,-1,sizeof(light));        for(i=1; i<=b; i++)        {            scanf("%d%d%d",&r,&c,&k);            mp[r][c]=1;            light[r][c]=k;        }        memset(vis,0,sizeof(vis));        ans=1000000;        dfs(1,1,0);        if(ans<1000000) printf("%d\n",ans);        else printf("No solution\n");    }    return 0;}/*ps:如果能夠過這組資料就不會TLE了7 7241 2 -11 4 -11 6 -12 1 -12 3 -12 5 -12 7 -13 2 -13 4 -13 6 -14 1 -14 3 -14 5 -14 7 -15 2 -15 4 -15 6 -16 1 -16 3 -16 5 -16 7 -17 2 -17 4 -17 6 -1ans: 25*/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.