zoukankan      html  css  js  c++  java
  • lightoj1018_状压dp

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1018

    题目描述:

      有n个点,问最少用几条无线长的线段把这n个点全部覆盖起来?
    解题思路:
      其实应该换一种枚举方式,先预处理出来每条线段,对每一个状态选择两个不在状态的点,然后画以两个点为端点的线,来进行状态转移。这个题目最重要的优化在于如何挑选不在状态的两个点,测试实力比较多,我们可以预处理出来每个状态未覆盖的点。

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <vector>
     7 #include <ctime>
     8 #include <queue>
     9 #include <list>
    10 #include <set>
    11 #include <map>
    12 using namespace std;
    13 #define INF 0x3f3f3f3f
    14 typedef long long LL;
    15 
    16 int x[20], y[20], dp[1<<16], line[20][20];
    17 vector <int> p[1<<16];
    18 void init()
    19 {
    20     for(int i = 0; i < (1<<16); i++)
    21     {
    22         for(int j = 0; j < 16; j++)
    23         {
    24             if((i & (1<<j)))
    25                 continue;
    26             p[i].push_back(j);
    27         }
    28     }
    29 }
    30 int check(int i, int j, int k)
    31 {
    32     int y2 = y[j], y1 = y[i], y3 = y[k];
    33     int x2 = x[j], x1 = x[i], x3 = x[k];
    34     if(y3*(x2-x1)==(y2-y1)*x3+x2*y1-x1*y2)
    35         return 1;
    36     else
    37         return 0;
    38     //return (y2-y1)*(x3-x2) == (y3-y2)*(x2-x1);
    39 }
    40 int main()
    41 {
    42     int t, n;
    43     scanf("%d", &t);
    44     init();
    45     for(int ca = 1; ca <= t; ca++)
    46     {
    47         scanf("%d", &n);
    48         for(int i = 0; i < n; i++)
    49             scanf("%d %d", &x[i], &y[i]);
    50         memset(line, 0, sizeof(line));
    51         for(int i = 0; i < n; i++)
    52         {
    53             line[i][i] = (1<<i);
    54             for(int j = i+1; j < n; j++)
    55             {
    56                 for(int k = 0; k < n; k++)
    57                 {
    58                     if(check(i, j, k))
    59                         line[i][j] |= (1<<k);
    60                 }
    61             }
    62         }
    63         memset(dp, INF, sizeof(dp));
    64         dp[0] = 0;
    65         for(int i = 0; i < (1<<n) -1; i++)//这里一定要减1,不然会re,我re了n发 = =
    66         {
    67             int x = p[i][0];
    68             for(int j = 0; j < p[i].size(); j++)
    69             {
    70                 int y = p[i][j];
    71                 dp[i|line[x][y]] = min(dp[i|line[x][y]], dp[i]+1);
    72             }
    73         }
    74         printf("Case %d: %d
    ", ca, dp[(1<<n)-1]);
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    java类加载器与双亲委派机制详解
    JAVA数据库连接池
    使用vue脚手架(vue-cli)快速搭建项目
    安装Vue.js
    @Autowired的使用:推荐对构造函数进行注释
    图解排序算法(三)之堆排序
    快速排序思想
    TCP与UDP区别总结
    JDBC
    solr单机版安装与集群搭建教程
  • 原文地址:https://www.cnblogs.com/luomi/p/5950721.html
Copyright © 2011-2022 走看看