海域, 冰山, 战舰

来源:互联网 发布:cf手游三头龙挂机软件 编辑:程序博客网 时间:2024/04/28 06:02

时间限制: 1 Sec
内存限制: 128 MB
提交: 33
解决: 11
[提交][状态][讨论版]

题目描述
给出一个n * n的海洋,#代表海域,.代表冰山,要在海域中放置k个战舰,战舰会攻击同一行同一列的其他战舰,所以同一行同一列不能放置其他战舰,问摆放战舰的方案数目C有多少种(数据保证C<2^31)。

输入
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,(n <= 8, k <= n)

随后的n行描述了的海洋的形状:每行有n个字符,其中 # 表示海域, . 表示冰山

输出
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

样例输入
2 1
#.
.#
4 4
…#
..#.
.#..
#…
样例输出
2
1

题意识先输入n表示n*n的海域,然后输入k表示需要放置k艘战舰,(k<=n),‘#’表示海域可以放战舰,‘.’表示不可以,且同一行同一列不能同时放置战舰,求可以有多少种放置方式

这道题与n皇后相似,都是说同一行同一列不能放置,但此题又比n皇后限制条件多一点,首先能放置的位置是固定的,某些点一定不能放,其次该题不似n皇后那样必须要放置n个,而是输入的k个,但大体上差不多

对于要求多少种方式的问题,若数据较小,便用dfs解决。

#include<cstdio>#include<cstring>int n,k,sum,flag;char map[10][10];//记录地图int w[10];//标记是否访问过int can(int a,int b){    if(!w[b]&&map[a][b]=='#'&&a>=0&&a<n)        return 1;//return 1 的情况不能分开写      return 0;//在if的情况下return 0就会出错 }void dfs(int a)//a表示第a行{    if(flag>=k)//不要在这里用个大括号写使flag=0         sum++;//方式    else if(a==n)//绝对不能少!!         return ;    else    {        for(int i=0;i<n;i++)//i表示第a行的第i个        {            if(can(a,i))            {                w[i]=1;                flag++;//记录已经放置好了多少艘战舰                dfs(a+1);//访问下一行                w[i]=0;//还原                flag--;//不要忘 ,很重要            }        }        dfs(a+1);//若第a行没有放或者不能放,就要从a+1行访问    }       }int main(){    while(~scanf("%d%d",&n,&k))    {        int i;        sum=0;        flag=0;        memset(w,0,sizeof(w));        for(i=0;i<n;i++)            scanf("%s",&map[i]);        dfs(0);//从第0行开始访问        printf("%d\n",sum);         }       return 0;}
#include<cstdio>#include<cstring>int n,k,sum;char map[10][10];int w[10];int can(int a,int b){    if(a<0||a>=n||b<0||b>=n)//越界        return 0;    if(w[b]||map[a][b]=='.')//访问过或者不能放置        return 0;    return 1;}void dfs(int a,int b)//表示放置到了第a行,已经放置了b个{    if(b==k)//放置完k个表示已经达到目标,方式sum++        sum++;    else if(a==n)//地图已经访问完了,结束        return ;    else    {        for(int i=0;i<n;i++)        {            if(!w[i]&&map[a][i]=='#')//为什么一定要写成立的情况,写不成立的情况就会WA             //第a行没有标记过并且第i列也没有被标记            {                w[i]=1;                dfs(a+1,b+1);                w[i]=0;            }        }        dfs(a+1,b);    }}int main(){    while(~scanf("%d%d",&n,&k))    {        sum=0;        memset(w,0,sizeof(w));//w[i]表示第i列是否被标记过        for(int i=0;i<n;i++)            scanf("%s",&map[i]);        dfs(0,0);        printf("%d\n",sum);         }    return 0;}
0 0
原创粉丝点击