标签:dfs
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;
} 
标签:dfs
原文地址:http://blog.csdn.net/u013532224/article/details/45604933