暑假集训--训练2 DFS

来源:互联网 发布:java 复制文件夹 编辑:程序博客网 时间:2024/06/06 10:55

A - N皇后问题
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Submit

Status

Description

在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。

Input

共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。

Output

共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。

Sample Input

1
8
5
0

Sample Output

1
92
10

经典的题目 蓝书上也有。因为N比较小,要事先打表,不然会超时

#include<iostream>#include<stdio.h>#include<cstring>#include<vector>#include<math.h>#include<sstream>#include<algorithm>using namespace std;const int MAX=15;int ans,n;int C[MAX]={0};int result[MAX]={0};void dfs(int cur){    if (cur==n) {ans++;return;}    for (int i=0;i<n;i++)    {        bool ok=true;        C[cur]=i;        for (int j=0;j<cur;j++)        {            if (C[cur]==C[j]||cur-C[cur]==j-C[j]||cur+C[cur]==j+C[j])            {                ok=false;                break;            }        }        if (ok)            dfs(cur+1);    }}int main(){    for (int i=1;i<=10;i++)    {        ans=0;        n=i;        memset(C,0,sizeof(C));        dfs(0);        result[i]=ans;    }    while (cin>>n&&n)        cout<<result[n]<<endl;    return 0;}

B - Prime Ring Problem
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Submit

Status

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 1 case.

Sample Input

6
8

Sample Output

Case 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

回溯法

#include<iostream>#include<stdio.h>#include<cstring>#include<vector>#include<math.h>using namespace std;int n;int cnt;bool used[25];int nums[25]={0};bool is_prime(int x){    if (x==2||x==1)        return true;    bool is=true;    for (int i=2;i<=sqrt(x);i++)    {        if (x%i==0)        {            is=false;            break;        }    }    return is;}void dfs(int x){    for (int i=1;i<=n;i++)    {        if (!used[i]&&is_prime(x+i)&&cnt!=n)        {            cnt++;            nums[cnt]=i;            used[i]=true;            dfs(i);            used[i]=false;            cnt--;        }        else if (cnt==n&&is_prime(nums[n]+nums[1]))        {            for (int i=1;i<=n-1;i++)                cout<<nums[i]<<" ";            cout<<nums[n]<<endl;            break;        }    }}int main(){    int times=0;    while (cin>>n)    {        cnt=1;        for (int i=0;i<25;i++) used[i]=false;        times++;        cout<<"Case "<<times<<":"<<endl;        used[1]=true;        nums[1]=1;        dfs(1);        cout<<endl;    }}

C - Network Saboteur
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu

Submit

Status

Description

A university network is composed of N computers. System administrators gathered information on the traffic between nodes, and carefully divided the network into two subnetworks in order to minimize traffic between parts.
A disgruntled computer science student Vasya, after being expelled from the university, decided to have his revenge. He hacked into the university network and decided to reassign computers to maximize the traffic between two subnetworks.
Unfortunately, he found that calculating such worst subdivision is one of those problems he, being a student, failed to solve. So he asks you, a more successful CS student, to help him.
The traffic data are given in the form of matrix C, where Cij is the amount of data sent between ith and jth nodes (Cij = Cji, Cii = 0). The goal is to divide the network nodes into the two disjointed subsets A and B so as to maximize the sum ∑Cij (i∈A,j∈B).

Input

The first line of input contains a number of nodes N (2 <= N <= 20). The following N lines, containing N space-separated integers each, represent the traffic matrix C (0 <= Cij <= 10000).
Output file must contain a single integer – the maximum traffic between the subnetworks.

Output

Output must contain a single integer – the maximum traffic between the subnetworks.

Sample Input

3
0 50 30
50 0 40
30 40 0

Sample Output

90
这个题目我看了好久才看懂,不过代码一次就写对了~dfs枚举不同的分法,选出最大的并记录就可以了。

#include<iostream>#include<stdio.h>#include<cstring>#include<vector>#include<math.h>#include<algorithm>const int MAX=20+3;using namespace std;int N;int maxSum;int C[MAX][MAX];bool divided[MAX];void dfs(int cnt){    if (cnt==N)    {        int sum=0;        for (int i=0;i<N;i++)        {            if (divided[i])            {                for (int j=0;j<N;j++)                {                    if (!divided[j])                        sum+=C[i][j];                }            }        }        if (sum>maxSum)            maxSum=sum;    }    else    {        divided[cnt]=true;        dfs(cnt+1);        divided[cnt]=false;        dfs(cnt+1);    }}int main(){    while (scanf("%d",&N)!=EOF)    {        for (int i=0;i<MAX;i++) divided[i]=false;        maxSum=0;        for (int i=0;i<N;i++)            for (int j=0;j<N;j++)                scanf("%d",&C[i][j]);        dfs(0);   ````    cout<<maxSum<<endl;    }    return 0;}

D - 速算二十四点
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Submit

Status

Description

速算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用’+’,’-‘,’*’,’/’运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数。

Input

每组输入数据占一行,给定四张牌。

Output

每一组输入数据对应一行输出。如果有解则输出”Yes”,无解则输出”No”。

Sample Input

A 2 3 6
3 3 8 8

Sample Output

Yes
No

这题想了好久还没思路,参考的网上代码的思路,自己写了一遍

#include<iostream>#include<stdio.h>#include<cstring>#include<vector>#include<math.h>#include<sstream>#include<algorithm>using namespace std;string temp[4];int num[4]= {0};bool flag;void dfs(int sum,int cur,int m){    if(flag)        return;    if(m==3)    {        if(sum+cur==24||sum-cur==24||sum*cur==24)            flag=1;        if(cur!=0&&sum%cur==0&&sum/cur==24)            flag=1;        return;    }    dfs(sum+cur,num[m+1],m+1);    dfs(sum-cur,num[m+1],m+1);    dfs(sum*cur,num[m+1],m+1);    if(cur!=0&&sum%cur==0)        dfs(sum/cur,num[m+1],m+1);    dfs(sum,cur+num[m+1],m+1);    dfs(sum,cur-num[m+1],m+1);    dfs(sum,cur*num[m+1],m+1);    if(num[m+1]!=0&&cur%num[m+1]==0)        dfs(sum,cur/num[m+1],m+1);}bool cmp(int a,int b){    return a<b;}int main(){    while (cin>>temp[0]>>temp[1]>>temp[2]>>temp[3])    {        flag=false;        for (int i=0; i<4; i++)        {            if (temp[i][0]=='A')                num[i]=1;            else if (temp[i][0]=='J')                num[i]=11;            else if (temp[i][0]=='Q')                num[i]=12;            else if (temp[i][0]=='K')                num[i]=13;            else            {                stringstream ss;                ss<<temp[i];                ss>>num[i];            }        }        sort(num,num+4,cmp);        do        {            dfs(num[0],num[1],1);        }        while (next_permutation(num,num+4)&&!flag);        if (flag) cout<<"Yes"<<endl;        else cout<<"No"<<endl;    }    return 0;}

E - Sticks
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u

Submit

Status

Description

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.

Input

The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.

Output

The output file contains the smallest possible length of original sticks, one per line.

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5

我觉得超级难的题目..也是参考的网上思路,进行了两次剪枝。dfs好难= =

#include<iostream>#include<stdio.h>#include<cstring>#include<vector>#include<math.h>#include<sstream>#include<algorithm>using namespace std;const int MAX=64+2;int N,sum,maxl,L;int lens[MAX]= {0};bool used[MAX];bool cmp(int a,int b){    return a>b;}bool dfs(int m,int left){    if (m==0&&left==0) return true;    if (left==0) left=L;    for (int i=0; i<N; i++)    {        if (!used[i]&&lens[i]<=left)        {            if (i>0)   //剪枝:如果有一根木棍在拼接过程中暂时不可用的话,那与其长度相等的木棍也不可用。            {                if (!used[i-1]&&lens[i]==lens[i-1])                    continue;            }            used[i]=true;            if (dfs(m-1,left-lens[i]))                return true;            else            {                used[i]=false;                if (lens[i]==left||left==L)    //剪枝:从长到短的搜索时若搜索失败,则比其短的也失败,因为题目给出的所有木棍都要用到。                    return false;            }        }    }    return false;}int main(){    while(scanf("%d",&N)&&N)    {        sum=0;        maxl=0;        for (int i=0; i<N; i++)        {            scanf("%d",&lens[i]);            sum+=lens[i];            maxl=max(maxl,lens[i]);        }        sort(lens,lens+N,cmp);        for (L=maxl; L<=sum/2; L++) //从给出的最长的木棍开始向上枚举L。        {            if (sum%L!=0) continue; //L一定能被sum整除            for (int i=0; i<N; i++) used[i]=false;//初始化            if (dfs(N,L))            {                printf("%d\n",L);                break;            }        }        if (L>sum/2)   //L比sum的一半长的话,就只能有一根木棍了。            printf("%d\n",sum);    }    return 0;}
0 0
原创粉丝点击