所谓的日常 #3 - 議溫明董卓叱丁原 饋金珠李肅說呂布

div.2

FZU 1477 进制转化

嘛...看起来大家之前做过这个题。至于原来ac的代码在这里交不能过,大概因为这里的数据更强一些吧。

 1 #include <stdio.h>
 2 
 3 int a[10000],tot;
 4 
 5 void work(int n,int m) {
 6     tot = 0;
 7     if (n == 0) {
 8         a[tot++] = 0;
 9     } else {
10         while (n) {
11             a[tot++] = n % m;
12             n /= m;
13         }
14     }
15     for (int i = tot - 1; i >= 0; -- i) {
16         if (a[i] >= 10)
17             putchar(a[i] - 10 + 'A');
18         else
19             printf("%d",a[i]);
20     }
21     puts("");
22 }
23 
24 int main() {
25     int n,m;
26     while (scanf("%d%d",&n,&m) == 2) {
27         work(n,m);
28     }
29 }
View Code

 

div.1

LightOJ 1018 Brush (IV)

给定二次元平面上n(<=16)个点,用直线把他们全部覆盖。问最少要几根直线。

那么 这是一道状态压缩dp。(不知道这是啥的出门左转学一下?,一言蔽之,就是dp[mask],mask为一个集合,mask的二进制位第i位为0表示没有i,1表示有i。或者可以这么说,你本要开dp[2][2][2][2][2]这么个状态,然而其实只要开dp[2 ^ 5]就好了)

然后大家知道 两个点确定一条直线。所以转移是枚举两个点,把这根直线覆盖的点们更新到状态里。这样的复杂度是O(n^3 * 2^n),所以我交的第一发TLE了。

考虑预处理。预处理出数组cover(i,j)表示选择i,j两个点构成的线段能够覆盖的点的集合。预处理O(n^3),dp部分O(n^2 * 2^n),又TLE了。

再次优化,由于每个点最终其实都被某根直线覆盖了,所以我们每次不需要枚举两个点,只需要枚举一个点,把它和当前未被覆盖的标号最小的点连起来就可以了。同样预处理O(n^3),dp部分O(n * 2^n),Accepted。

然后,判断3点共线,使用叉积即可,也就是代码里的det()函数。

然后...代码里有一些位运算,关于位运算的优先级问题 可以百度一下,有张表。但是建议如果搞不清运算顺序的话 就加括号吧。

 1 #include <stdio.h>
 2 
 3 const int N = 16;
 4 
 5 struct Point {
 6     Point() {}
 7     Point(int _x,int _y) : x(_x),y(_y) {}
 8     Point operator - (const Point &rhs) const {
 9         return Point(x - rhs.x,y - rhs.y);
10     }
11     int x,y;
12 };
13 
14 int det(const Point &a,const Point &b) {
15     return a.x * b.y - a.y * b.x;
16 }
17 
18 Point points[N];
19 
20 const int INF = 0x3f3f3f3f;
21 int dp[1 << N];
22 int n;
23 int cover[N][N];
24 
25 inline void update(int &a,int b) {
26     if (a > b) a = b;
27 }
28 
29 int work() {
30     for (int mask = 0; mask < 1 << n; ++ mask) {
31         dp[mask] = INF;
32     }
33     for (int i = 0; i < n; ++ i) {
34         for (int j = i + 1; j < n; ++ j) {
35             int mask = 0;
36             for (int k = 0; k < n; ++ k) {
37                 if (det(points[i] - points[k],points[j] - points[k]) == 0)
38                     mask |= 1 << k;
39             }
40             cover[i][j] = mask;
41         }
42     }
43     dp[0] = 0;
44     for (int mask = 0; mask < 1 << n; ++ mask) {
45         int x = -1;
46         for (int i = 0; i < n; ++ i) {
47             if (!(mask >> i & 1)) {
48                 x = i;
49                 break;
50             }
51         }
52         if (x == -1) continue;
53         update(dp[mask ^ 1 << x],dp[mask] + 1);
54         for (int i = x + 1; i < n; ++ i) {
55             update(dp[mask | cover[x][i]],dp[mask] + 1);
56         }
57     }
58     return dp[(1 << n) - 1];
59 }
60 
61 int main() {
62     int cas,ca = 0;
63     scanf("%d",&cas);
64     while (cas--) {
65         scanf("%d",&n);
66         for (int i = 0; i < n; ++ i) {
67             scanf("%d%d",&points[i].x,&points[i].y);
68         }
69         printf("Case %d: %d\n",++ca,work());
70     }
71 }
View Code

 

posted @ 2015-12-22 20:02  zstuACM  阅读(205)  评论(0编辑  收藏  举报