zoukankan      html  css  js  c++  java
  • 18.5.25 深搜作业

    A:棋盘问题

    描述

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。输入输入含有多组测试数据。
    每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
    当为-1 -1时表示输入结束。
    随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。
    输出对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。

    样例输入

    2 1
    #.
    .#
    4 4
    ...#
    ..#.
    .#..
    #...
    -1 -1
    

    样例输出

    2
    1
    

    来源

    蔡错@pku

     1 #include <iostream>
     2 #include <string>
     3 #include <cstdio>
     4 #include <memory.h>
     5 #include <map>
     6 #include <math.h>
     7 using namespace std;
     8 const int maxn =15;
     9 int hangput[maxn], lieput[maxn],chess[maxn][maxn];
    10 char thisline[maxn];
    11 int n, k, sum=0;
    12 
    13 void solve(int hang,int num) {
    14     if (num == 0)
    15     {
    16         sum++;
    17         return;
    18     }
    19         for(int j=1;j<=n;j++)
    20             if (chess[hang][j] && !lieput[j])
    21             {
    22                 //place the chess
    23                 if (num - 1 == 0)
    24                     sum++;
    25                 else
    26                 {
    27                     lieput[j] = 1;
    28                     for (int i = hang + 1; i <= n - num + 2; i++)
    29                         solve(i, num - 1);
    30                     lieput[j] = 0;
    31                 }
    32             }
    33 }
    34 
    35 void init() {
    36     while (scanf("%d%d", &n, &k) && (n != -1 || k != -1)) {
    37         sum = 0;
    38         for (int i = 1; i <= n; i++)
    39             for(int j=1;j<=n;j++)
    40         {
    41                 char ch;
    42                 cin >> ch;
    43                 if (ch == '#')
    44                     chess[i][j] = 1;
    45                 else chess[i][j] = 0;
    46         }
    47         for (int i = 1; i <= n - k + 1; i++)
    48             solve(i, k);
    49         printf("%d
    ", sum);
    50     }
    51 }
    52 
    53 int main()
    54 {
    55     init();
    56     return 0;
    57 }
    View Code

    比较水,和后面一道形成了鲜明的对比

    B:生日蛋糕

    描述

    7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。
    设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。
    由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
    令Q = Sπ
    请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。
    (除Q外,以上所有数据皆为正整数)
    输入有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。输出仅一行,是一个正整数S(若无解则S = 0)。

    样例输入

    100
    2

    样例输出

    68

    提示

    圆柱公式
    体积V = πR2H
    侧面积A' = 2πRH
    底面积A = πR2
    来源

    Noi 99

     1 #include <iostream>
     2 #include <string>
     3 #include <cstdio>
     4 #include <memory.h>
     5 #include <algorithm>
     6 #include <math.h>
     7 using namespace std;
     8 const int maxn =15;
     9 int n,m,smin=999999;
    10 const int maxnum = 9999999;
    11 
    12 void solve(int v,int k,int topr,int toph,int S) {
    13     if (k == 0)
    14     {
    15         if (v == 0)
    16             smin=min(S,smin);
    17         return;
    18     }
    19     if (S + 2 * (v / topr) > smin)
    20         return;
    21     if ((unsigned)(topr - 1)*(unsigned)(topr - 1)*(unsigned)(toph - 1)*k < v)
    22         return;
    23     int topv = v - k * (k - 1) / 2,_min=maxnum;
    24     for(int i=topr-1;i>=k;i--)
    25         for (int j = k; j < toph; j++)
    26         {
    27             int _v = i * i*j;
    28             if (_v*k < v)
    29                 continue;
    30             if (_v<v / k)
    31                 continue;
    32             if (_v > topv)
    33                 continue;
    34             int s = 2 * i*j;
    35             if (s + k*(k-1)/2 > smin)
    36                 continue; 
    37             int sums = s + S;
    38             if (k == m)
    39                 sums+=i*i;
    40             solve(v - _v, k - 1, i, j, sums);
    41         }
    42 }
    43 
    44 void init() {
    45     scanf("%d%d", &n, &m);
    46     int maxr = sqrt(n);
    47     solve(n, m, maxr, n,0);
    48     printf("%d
    ", smin);
    49 }
    50 
    51 int main()
    52 {
    53     init();
    54     return 0;
    55 }
    View Code

    一开始我把深搜函数设置为返回S值,如果不能就返回一个超大值……果断TLE。后来想是不是这样每次调用min太慢了,改成了void,直接在函数中在边界条件做判断取最小值,快了巨多……

    一开始我的剪枝全部在循环内部,我也在想这样剪枝是不是有点弱……果然太弱……

    其实……剪枝只要一个就可以了……就是那个 if (S + 2 * (v / topr) > smin) (最优化剪枝)

    最难想,但剪掉的最多

    其他……感觉不是特别有用……

    然后 (unsigned)(topr - 1)*(unsigned)(topr - 1)*(unsigned)(toph - 1)*k < v 不加 unsigned 会WA,因为会出现溢出。感谢洛谷提供的数据TUT

    但是那个条件好像没什么用……

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    449. Serialize and Deserialize BST
    114. Flatten Binary Tree to Linked List
    199. Binary Tree Right Side View
    173. Binary Search Tree Iterator
    98. Validate Binary Search Tree
    965. Univalued Binary Tree
    589. N-ary Tree Preorder Traversal
    eclipse设置总结
  • 原文地址:https://www.cnblogs.com/yalphait/p/9087920.html
Copyright © 2011-2022 走看看