HDU 4499 Cannon

原创的思维和代码永远比看题解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;
}