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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值