• 【Luogu】【关卡2-9】带有技巧的搜索(2017年10月)


    任务说明:这里的搜索不仅包含了dfs和bfs,还包括剪枝、记录等技巧以加快速度。

    [USACO06FEB]数字三角形Backward Digit Su…
    滑雪
    吃奶酪
    靶形数独

    P1118 [USACO06FEB]数字三角形Backward Digit Su…

    有这么一个游戏:写出一个1~N的排列a[i],然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少1,直到只剩下一个数字位置。

    最后得到16这样一个数字。

    现在想要倒着玩这样一个游戏,如果知道N,知道最后得到的数字的大小sum,请你求出最初序列a[i],为1~N的一个排列。若答案有多种可能,则输出排序最小的那一个。

    解答:第一次我想直接next_permutation,然后在嵌套循环计算顶层数字,结果TLE了好几个点。

    后来看了题解,大家都说的杨辉三角,我还是没懂。专门搜索了题解才看懂。

    最后的结果其实是一个杨辉三角。(拿样例来说,第4层的杨辉三角是1 3 3 1; 1∗3+3∗1+3∗2+1∗4=16)

    然后知道杨辉三角怎么用了之后,直接dfs求全排列,如果超过了sum值就回溯。 

     1 #include <bits/stdc++.h>
     2 #include <string>
     3 using namespace std;
     4 
     5 int n, sum;
     6 int yanghuisanjiao[20][20] = {0};
     7 int used[20] = {0};
     8 
     9 void print(vector<int>& vec, std::string& strDes) {
    10     printf("%s: ", strDes.c_str());
    11     for (int i = 0; i < vec.size(); ++i) {
    12         printf("%d ", vec[i]);
    13     }
    14     printf("
    ");
    15 }
    16 
    17 void print(vector<int>& vec) {
    18     for (int i = 0; i < vec.size(); ++i) {
    19         printf("%d ", vec[i]);
    20     }
    21     printf("
    ");
    22 }
    23 
    24 bool dfs(int level, vector<int>& permutation, int cal_sum, int idx) {
    25     if (level == n + 1) {
    26         if (cal_sum == sum) {
    27             print(permutation);
    28             return true;
    29         }
    30         return false;
    31     }
    32     for (int i = 0; i < n; ++i) {
    33         if (!used[i+1]) {
    34             permutation[idx] = i + 1;
    35             used[i+1] = 1;
    36             //如果求和大于sum,就剪枝
    37             if (cal_sum + yanghuisanjiao[n-1][idx] * permutation[idx]  > sum) {
    38                 used[i+1] = false;
    39                 return false;
    40             }
    41             bool ans = dfs(level + 1, permutation, cal_sum + yanghuisanjiao[n-1][idx] * permutation[idx], idx + 1);
    42             if (ans == true) {
    43                 return true;
    44             }
    45             used[i+1] = 0;
    46         }
    47     }
    48     //找到最后也没找到, 就return false
    49     return false;
    50 }
    51 
    52 
    53 int main() {
    54     cin >> n >> sum;
    55 
    56     //[1]计算杨辉三角
    57     for (int i = 0; i < n ; ++i) {
    58         for (int j = 0; j <= i; ++j) {
    59             if (j == 0 || j == i ) {
    60                 yanghuisanjiao[i][j] = 1;
    61             }
    62             else {
    63                 yanghuisanjiao[i][j] = yanghuisanjiao[i-1][j-1] + yanghuisanjiao[i-1][j];
    64             }
    65         }
    66     }
    67 
    68     //[2]深搜求全排列
    69     vector<int> permutation(n, 0);
    70     dfs(1, permutation, 0, 0);
    71     return 0;
    72 }
    View Code

    P1433 吃奶酪

    房间里放着n块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在(0,0)点处。

    输入:第一行一个数n (n<=15),接下来每行2个实数,表示第i块奶酪的坐标。两点之间的距离公式=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))

    输出:一个数,表示要跑的最少距离,保留2位小数。

    题解:显然贪心不行。那么只能搜索每个点的顺序,求最小值的距离。

     1 //这个题目最后也是90分,第五个点TLE,没想明白为啥
     2 #include<bits/stdc++.h>
     3 #include<unistd.h>
     4 #include <sys/time.h>
     5 using namespace std;
     6 
     7 typedef pair<double, double> P;
     8 int n;
     9 
    10 double ans = DBL_MAX;
    11 int addx[4] = {0, -1, 0, 1};
    12 int addy[4] = {-1, 0, 1, 0};
    13 
    14 void print(vector<vector<double>> vec) {
    15     printf("===============debug============
    ");
    16     for (int i = 0; i < vec.size(); ++i) {
    17         for(int j = 0; j < vec.size(); ++j) {
    18             printf("%.2f ", vec[i][j]);
    19         }
    20         printf("
    ");
    21     }
    22     printf("===============end==============
    ");
    23 }
    24 
    25 void dfs(const vector<P>& coor, const double dis[16][16], vector<int>& used, int level, double tmpans, int pre) {
    26     if (tmpans >= ans) {
    27         return;
    28     }
    29     if (level == coor.size()) {
    30         if (ans > tmpans) { ans = tmpans;}
    31         return;
    32     }
    33     for(int i = 1; i < coor.size(); ++i) {
    34         double temp = dis[pre][i] + tmpans;
    35         if (!used[i] && temp < ans) {
    36             used[i] = 1;
    37             dfs(coor, dis, used, level+1, temp, i);
    38             used[i] = 0;
    39         }
    40     }
    41 }
    42 
    43 int main() {
    44         struct timeval tv;
    45         gettimeofday(&tv, NULL);
    46         printf("%ld
    ", tv.tv_sec);
    47     scanf("%d", &n);
    48     vector<P> coor(n + 1);
    49     coor[0] = make_pair(0.0, 0.0);
    50     for(int i = 1; i <= n; ++i){
    51         double x, y;
    52         scanf("%lf %lf", &x, &y);
    53         coor[i] = make_pair(x, y);
    54     }
    55 
    56     double dis[16][16] = {0.0};
    57     for(int i = 0; i <= n; ++i) {
    58         for(int j = i; j <= n; ++j) {
    59             dis[i][j] = dis[j][i]
    60             = sqrt((coor[i].first - coor[j].first)*(coor[i].first - coor[j].first)
    61                 + (coor[i].second - coor[j].second)*(coor[i].second - coor[j].second));
    62         }
    63     }
    64 
    65     vector<int> use(n+1);
    66     use[0] = 1;
    67     dfs(coor, dis, use, 1, 0.0, 0);
    68     printf("%.2f
    ", ans);
    69         gettimeofday(&tv, NULL);
    70         printf("%ld
    ", tv.tv_sec);
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    各大高校OJ网站
    项目中调试SQLServer 方便的查看SQL语句的执行时间的方法
    一个联合查询的优化,排行榜排名
    IEdevelopToolbar ie浏览器的css代码调试工具
    SQL Server 2016/2014/2012/2008/2005/2000简体中文企业版下载地址
    sql server 数据库学习
    增加路由ip
    HTTP Error 500.0
    远程的一些知识
    Windows内置系统账户:Local system/Network service/Local Service 区别
  • 原文地址:https://www.cnblogs.com/zhangwanying/p/7634741.html
Copyright © 2020-2023  润新知