hdu4499 超暴力dfs回溯

Description

In Chinese Chess, there is one kind of powerful chessmen called Cannon. It can move horizontally or vertically along the chess grid. At each move, it can either simply move to another empty cell in the same line without any other chessman along the route or perform an eat action. The eat action, however, is the main concern in this problem. 
An eat action, for example, Cannon A eating chessman B, requires two conditions: 
1、A and B is in either the same row or the same column in the chess grid. 
2、There is exactly one chessman between A and B. 
Here comes the problem. 
Given an N x M chess grid, with some existing chessmen on it, you need put maximum cannon pieces into the grid, satisfying that any two cannons are not able to eat each other. It is worth nothing that we only account the cannon pieces you put in the grid, and no two pieces shares the same cell.

Input

There are multiple test cases. 
In each test case, there are three positive integers N, M and Q (1<= N, M<=5, 0<=Q <= N x M) in the first line, indicating the row number, column number of the grid, and the number of the existing chessmen. 
In the second line, there are Q pairs of integers. Each pair of integers X, Y indicates the row index and the column index of the piece. Row indexes are numbered from 0 to N-1, and column indexes are numbered from 0 to M-1. It guarantees no pieces share the same cell.

Output

There is only one line for each test case, containing the maximum number of cannons.

Sample Input

4 4 2 
1 1 1 2 
5 5 8 
0 0 1 0 1 1 2 0 2 3 3 1 3 2 4 0 

Sample Output

8 
9




原創的思維和代碼永遠比看題解A的興奮的多!

原創的思維和代碼永遠比看題解A的興奮的多!!

原創的思維和代碼永遠比看題解A的興奮的多!!!

原創的思維和代碼永遠比看題解A的興奮的多!!!!

原創的思維和代碼永遠比看題解A的興奮的多!!!!!

原創的思維和代碼永遠比看題解A的興奮的多!!!!!!

哪怕算法效率上差別人很多

昨天的周常比賽我看到這題就知道用暴力回溯   想想應該和八皇后難度上差不了多少  就放到最後一小時再寫   結果就懵逼了

越寫越亂   最後也沒寫出來    晚上也一直在想  結果發現   越深究,我的思路漏洞越多,這個問題也變得越來越有趣,今天早上還是被我A了  真是痛快

思路就是暴力回溯   具體的  見註釋(其實我不建議你看我代碼,因爲我覺得太臭了,但畢竟是自己親生的,哈哈哈哈哈哈哈哈哈哈


AC code


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>

using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
int ans,row,col;
int mat[10][10];//整個棋盤我分爲4種狀態  0 空   1  其他棋子   2  放炮排斥位置   3  炮

void update(int x,int y)
{
    bool flag=true;
    for(int i=y+1; i<col-1&&flag; i++)//對座標右行進行更新
        if(mat[x][i]==1&&mat[x][i+1]==1) break;//遇到兩個相鄰的其他棋子就不需要了
        else if(mat[x][i]==1)//如果只是一個其他棋子
            for(int j=i+1; j<col; j++)
                if(mat[x][j]==1){flag=false;break;}//再碰到一個其他棋子
                else mat[x][j]=2;
    for(int i=0; i<y; i++)//對座標座標進行更新
        if(mat[x][i]==3&&mat[x][i+1]!=1&&mat[x][i+2]!=1)//如果前面有炮並且沒有兩個相鄰的其他棋子阻隔   (其實這裏還寫不大好,抄了小路,既然A了就算了
            for(int j=y+1; j<col; j++)
                if(mat[x][j]==1) break;//碰到一個其他棋子
                else mat[x][j]=2;
    flag=true;
    for(int i=x+1; i<row-1&&flag; i++)
        if(mat[i][y]==1&&mat[i+1][y]==1) break;
        else if(mat[i][y]==1)
            for(int j=i+1; j<row; j++)
                if(mat[j][y]==1) {flag=false;break;}
                else mat[j][y]=2;
    for(int i=0; i<x; i++)
        if(mat[i][y]==3&&mat[i+1][y]!=1&&mat[i+2][y]!=1)
            for(int j=x+1; j<row; j++)
                if(mat[j][y]==1) break;
                else mat[j][y]=2;
}

void dfs(int r,int num,int add,int st)
{
    if(r==row)
    {
        ans=max(num,ans);
        return ;
    }
    int temprow[7],tempcol[7],tt;
    for(int i=st; i<col; i++)
    {
        if(mat[r][i]==0)
        {
            for(int j=0; j<col; j++)
                temprow[j]=mat[r][j];
            for(int j=0; j<row; j++)
                tempcol[j]=mat[j][i];
            tt=mat[r][i];//最傻最暴力的備份方法
            mat[r][i]=3;//放炮
            update(r,i);//更新
            if(add<2&&i<col-1) dfs(r,num+1,add+1,i+1); //對於一行來說   最多可以放3個炮  同行遞歸
            dfs(r+1,num+1,0,0);//同行遞歸不行就下一行
            mat[r][i]=tt;//還原
            for(int j=0; j<col; j++)
                mat[r][j]=temprow[j];
            for(int j=0; j<row; j++)
                mat[j][i]=tempcol[j];
        }
    }
    dfs(r+1,num,0,0);//也有可能我一正行都不能放反而更優
}

int main()
{
    int num,x,y;
    while(scanf("%d%d%d",&row,&col,&num)!=EOF)
    {
        memset(mat,0,sizeof mat);
        for(int i=0; i<num; i++)
        {
            scanf("%d%d",&x,&y);
            mat[x][y]=1;
        }
        ans=0;
        dfs(0,0,0,0);
        printf("%d\n",ans);
    }
    return 0;
}


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