HDU-4499-Cannon(DFS剪枝)

Cannon

Problem 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
 

解题思路:

给一个nxm的棋盘,有一些棋子。让在上面放尽量多的炮。使得炮不能互相攻击。由象棋基础可以知道题目也解释了,炮是可以跳一格打的。然后可以打别的棋子,只要满足炮不打到炮就行了。

暴力出奇迹,直接枚举每个点的两种状态,但是2^25次方有点受不了。所以还是需要剪枝。也就是按顺序枚举,枚举到不可行的状态就不往下搜了,而不是到最后来判断。写一个检查函数,因为放下一个棋子只和当先行和当前列有关,所以并不复杂。暴力时间够的。
这样只要搜到了最后一格就是可行状态。答案+1就行了。

AC代码:

#include <bits/stdc++.h>
#include <utility>
#include <string>
#define int long long
using namespace std;
const int mod = 1e9+7;
const int N = 2e5+10;
int mp[6][6];
int ans;
int m,n;

int check(int x,int y)
{
    if(y >= 2)
    {
        for(int i = 0 ; i < y-1 ; i ++)
            if(mp[x][i] == 1)
            {
                int cnt = 0;
                for(int j = i+1 ; j < y ; j ++)
                {
                    if(mp[x][j] != 0)
                        cnt++;
                }
                if(cnt == 1)
                    return 0;
            }
    }
    if(x >= 2)
    {
        for(int i = 0 ; i < x-1 ; i ++)
            if(mp[i][y] == 1)
            {
                int cnt = 0;
                for(int j = i+1 ; j < x ; j ++)
                {
                    if(mp[j][y] != 0)
                        cnt++;
                }
                if(cnt == 1)
                    return 0;
            }
    }
    return 1;
}


void dfs(int x,int y,int sum)
{
    if(y == m){
        ans = max(ans,sum);
        return;
    }
    if(mp[x][y] == 2)
        dfs((x+1)%n,y+(x%n == n-1),sum);
    else{
        mp[x][y] = 1;
        if(check(x,y))
            dfs((x+1)%n,y+(x%n == n-1),sum+1);
        mp[x][y] = 0;
        dfs((x+1)%n,y+(x%n == n-1),sum);
    }
}



signed main()
{
    while(cin>>m>>n)
    {
        int t;
        cin>>t;
        ans = 0;
        memset(mp,0,sizeof(mp));
        for(int i = 0 ; i  < t ; i ++)
        {
            int x,y;
            cin>>x>>y;
            mp[y][x] = 2;
        }
        dfs(0,0,0);
        cout<<ans<<endl;
    }
    return 0;
}

发布了104 篇原创文章 · 获赞 7 · 访问量 4069

猜你喜欢

转载自blog.csdn.net/qq_43461168/article/details/104131695