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
8 9
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4499
题意:给你一个n*m的棋盘,有q个点已经放了棋。问最多还能放多少炮。要求炮与炮之间不能互相攻击。也就是两个炮直接不能隔着炮或者隔着棋。
做法:棋盘大小最大25个格子。2^25=3*10^7。如果枚举每个状态还要判断可不可行会超时。 所以我用了dfs。每次那个位置如果没有棋,就摆上炮dfs下去,每次摆判断和正上方一排冲突不冲突,还有左边一排冲不冲突。不冲突才可以摆。 再把炮去掉dfs下去。如果没有棋,就dfs不摆炮就行了。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
int n,m,q;
int mp[5][5];
int ass;
int dfs(int nw,int fa)
{
if(nw==n*m)
{
return fa;
}
int x=nw/m;
int y=nw%m;
int maxx=fa;
if(mp[x][y]!=1)
{
int flag=0;
if(mp[1][0]==2&&mp[3][0]==2&&nw==20)
int kk=1;
for(int i=x-1;i>=0;i--)
{
if(flag==1&&mp[i][y]==2)
flag=2;
if(flag==1&&mp[i][y]==1)
break;
if(flag==0&&(mp[i][y]==1||mp[i][y]==2))//炮
flag=1;
}
int flag2=0;
for(int i=y-1;i>=0;i--)
{
if(flag2==1&&mp[x][i]==2)
flag2=2;
if(flag2==1&&mp[x][i]==1)
break;
if(flag2==0&&(mp[x][i]==1||mp[x][i]==2))//炮
flag2=1;
}
if(flag!=2&&flag2!=2)
{
mp[x][y]=2;
maxx=max(maxx,dfs(nw+1,fa+1));
mp[x][y]=0;
maxx=max(maxx,dfs(nw+1,fa));
}
else
maxx=max(maxx,dfs(nw+1,fa));
}
else
maxx=max(maxx,dfs(nw+1,fa));
return maxx;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
memset(mp,0,sizeof mp);
ass=0;
for(int i=0;i<q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x][y]=1;
}
printf("%d\n",dfs(0,0));
}
return 0;
}
原文:http://blog.csdn.net/u013532224/article/details/45604933