DFS大法好之我都不会做系列

A - 学dfs你不会放棋盘?你TM逗我!
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u

Description
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。

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

Sample Input
2 1
#.
.#
4 4
…#
..#.
.#..
#…
-1 -1

Sample Output
2
1

中文题目,大家都看得懂。。没什么特别的,还是DFS咯。。

//POJ 1321
//

#include <iostream>


using namespace std;

int size;
int ans;

struct newmap {
    char map [10][10];    //棋盘
    int x;                //上一个棋子的行数
};


void DFS(newmap temp,int chess)
{
    if(chess==0)
    {
        ans++;
        return;
    }
    int i,j;
    for(i=temp.x+1;i<=(size-chess);i++)
    {
        for(j=0;j<size;j++)
        {
            if(temp.map[i][j]=='#')
            {
                newmap temp2;
                temp2=temp;
                temp2.x=i;
                int k;
                for (k = i+1 ; k < size ; k ++)
                {//更新棋盘,因为,不会再向该行和该行之前的棋盘搜索,故只用更新该行下同列的棋盘
                temp2.map[k][j]='.';
                }
                DFS(temp2,chess-1);
            }


        }
    }    

}

int main()
{
    int chess;
    while(scanf("%d %d ",&size,&chess))
   {

       if(size==-1&&chess==-1)
           return 0;
       newmap map;
       map.x=-1;
       for(int i=0;i<size;i++)
       {
           scanf("%s",map.map[i]);
       }
       DFS(map,chess);
       cout<<ans<<endl;
       ans=0;
       size=0;
       chess=0;
   }
}

B - 放棋盘简单,看看这个,好像很黄很暴力的样子!
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u

Description
Given a positive integer n, write a program to find out a nonzero multiple m of n whose decimal representation contains only the digits 0 and 1. You may assume that n is not greater than 200 and there is a corresponding m containing no more than 100 decimal digits.

Input
The input file may contain multiple test cases. Each line contains a value of n (1 <= n <= 200). A line containing a zero terminates the input.

Output
For each value of n in the input print a line containing the corresponding value of m. The decimal representation of m must not contain more than 100 digits. If there are multiple solutions for a given value of n, any one of them is acceptable.

Sample Input
2
6
19
0

Sample Output
10
100100100100100100
111111111111111111

题目说的是,给你一个数,让你找一个只由1、0组成的数,使得这个数与所给数成倍数关系。
这题DFS的关键是 从1开始每一步都在当前数字的基础上*10以及*10+1这样生成的数字每一位才要么为1要么为0,如此下去,直到生成的数符合要求为止。

#include "iostream"
#include "math.h"
using namespace std;

int flag=0;   //to mark if target number has been found
void dfs(unsigned long long NowNumber,int n)
{
    if(NowNumber>3222222222222222222) return;
    if(flag==1) return;
    else
    {
        if(NowNumber%n==0) //当前数是n的倍数
        {
            cout<<NowNumber<<endl;
            flag=1;
            return;
        }
        else
        {
            dfs(NowNumber*10,n);
            if(flag==1) return; //once the required number is found stop
            dfs(NowNumber*10+1,n);
            if(flag==1) return; //the same as above
        }

    }

}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0) return 0;
        dfs(1,n);    //initial    start with one
        flag=0;
    }
    return 0;
}

C - 素数搞基环?!
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, …, n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.

Note: the number of first circle should always be 1.

Input
n (0 < n < 20).

Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.

You are to write a program that completes above process.

Print a blank line after each case.

Sample Input
6
8

Sample Output
Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

输入一个n,代表这个环上有n个圈,往这个n个圈里不重复地分别填入1~n。第一个圈总是填的1。同时还要求相邻的数之和是质数。本题需要特别处理是第n个环所填的数,因为与这个位置相邻的两个环中,有一个是起点。

#include "iostream"
using namespace std;
int num_mark[9999];  //0 hasnt been used   1 used
int ncase=0;
bool is_prime(int n)
{
    if(n<2)
        return false;
    for (int i=2;i*i<=n;i++)
    {
        if(n % i == 0)
            return false;
    }
    return true;
}
void dfs(int n,int pos,int circle[]) //i is current number
{
    if(pos>=n)
    {
        //print
        int i=1;
        for(i=1;i<=n;i++)
        {
            cout<<circle[i];
            if(i!=n)
                cout<<" ";
            if(i==n)
                cout<<endl;
        }

        return;
    }
    else
    {
        for(int i=1;i<=n;i++)
        {
            if(num_mark[i]==0)
            {

                if((pos+1)==n)  //if next pos reach the last loop
                {
                    if(is_prime(i+circle[1])&&is_prime(i+circle[pos]))
                    {
                        num_mark[i]=1;
                        circle[pos+1]=i;
                        dfs(n,pos+1,circle);
                        num_mark[i]=0;
                    }
                }
                else
                {
                    if(is_prime(i+circle[pos]))
                    {
                        num_mark[i]=1;
                        circle[pos+1]=i;
                        dfs(n,pos+1,circle);
                        num_mark[i]=0;
                    }
                }

            }

        }

    }
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        ncase++;
        memset(num_mark,0,sizeof(num_mark));
        num_mark[1]=1;
        int circle[25];
        circle[1]=1;
        cout<<"Case "<<ncase<<":"<<endl;
        dfs(n,1,circle);
        cout<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值