hdu 1925 A Foldy but a Goody---点的旋转

Posted fzl194

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 1925 A Foldy but a Goody---点的旋转相关的知识,希望对你有一定的参考价值。

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1925

题目大意:

假设有一条很长的线,对它进行n次对折(n <= 30),给出每次对折的方向---向上对折或者向下对折。这样吧这根线分成m小段,m = 2^n,将这条线展开,对应的每个折痕做一个90度的角,把起始点作为第0号点,坐标为(0, 0),第一个拐角坐标为(1,0),求第k个点的坐标。

解题思路:

先动手折起来。

        第一次对折,设折叠点为P1,把这条线分成两部分,接下来的n-1次操作,对这两部分的操作完全一样,所以这条线展开的时候,前一半和后一半的形状是完全一样的,只是后一半是前一半绕P1点顺时针(或者逆时针)90度而来的。这样,已知起始点的坐标为(0, 0)如果知道P1的坐标,那么可以直接求出最后一点的坐标。要求出P1的坐标,可以同理继续下去,P1是起始点绕P2顺时针或逆时针转90度得来的......而我们知道第n次折叠的点Pn = (1, 0)因此可以迅速求处所有折叠点的坐标。

       接着对于第k个转折点的坐标也可以用类似的方法,观察一下,比如4步操作LLUL后,有16个点,求第13个点,就是第3个点绕第8个点旋转而来,至于顺时针还是逆时针,由于绕的是第8个点旋转而来,为2的三次方,总共是2的4次方,所以应该是第一次的操作,因为第一次操作时,将前半部分和后半部分重叠,此时3和13正好重叠。

点旋转公式

x1,y1绕点x0,y0逆时针旋转a度

x2 = (x1 - x0)cos(a) - (y1 - y0)sin(a) + x0     

y2 = (x1 - x0)sin(a) + (y1 - y0)cos(a) + y0

所以顺时针旋转90度等价于逆时针旋转-90度

向下对应着逆时针 向上对应顺时针(折纸得出的规律)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 struct node
 5 {
 6     int x, y;
 7     node(){}
 8     node(int x, int y):x(x), y(y){}
 9 };
10 node shun(node a, node b)//a点绕b点顺时针90度
11 {
12     node c;
13     c.x = b.x - b.y + a.y;
14     c.y = b.y + b.x - a.x;
15     return c;
16 }
17 node ni(node a, node b)//a点绕b点逆时针90度
18 {
19     node c;
20     c.x = b.x + b.y - a.y;
21     c.y = b.y - b.x + a.x;
22     return c;
23 }
24 map<int, node>Flip;
25 string s;
26 int n, k;
27 node dfs(int x)
28 {
29     //cout<<x<<endl;
30     if(Flip.count(x))return Flip[x];
31     int t = 1, tmp, cnt = 0;
32     while(t <= x)t *= 2, cnt++;
33     tmp = t - x;
34     if(s[n - cnt] == L)
35         return Flip[x] = ni(dfs(tmp), Flip[1 << (cnt - 1)]);
36     else
37         return Flip[x] = shun(dfs(tmp), Flip[1 << (cnt - 1)]);
38 }
39 int main()
40 {
41     int T;
42     cin >> T;
43     while(T--)
44     {
45         Flip.clear();
46         cin >> s >> k;
47         n = s.size();
48         Flip[1] = node(1, 0);
49         node tmp(0, 0);
50         Flip[0] = node(0, 0);
51         for(int i = 1; i <= n; i++)
52         {
53             if(s[n - i] == L)//向下为逆时针
54                 Flip[(1<<i)] = ni(tmp, Flip[1<<(i - 1)]);
55             else
56                 Flip[(1<<i)] = shun(tmp, Flip[1<<(i - 1)]);
57             //cout<<Flip[1<<i].x<<" "<<Flip[1<<i].y<<endl;
58         }
59         dfs(k);
60         cout<<"("<<Flip[k].x<<","<<Flip[k].y<<")
";
61     }
62     return 0;
63 }

 

以上是关于hdu 1925 A Foldy but a Goody---点的旋转的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4775 Infinite Go(暴力)

hdu6601 Keen On Everything But Triangle 主席树+斐波那契数列妙用

BZOJ1925: [Sdoi2010]地精部落 DP+滚动数组

bzoj1925 [Sdoi2010]地精部落

bzoj 1925 [Sdoi2010]地精部落(DP)

HUD 1171 Big Event in HDU(01背包)