• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            糯米

            TI DaVinci, gstreamer, ffmpeg
            隨筆 - 167, 文章 - 0, 評論 - 47, 引用 - 0
            數據加載中……

            Linux內核通過inline hook實現隱藏進程

            這是我們操作系統的大作業。
            原理就是inline hook 那個 proc 文件系統,根目錄下的 readdir 的函數。
            替換掉第三個參數,filldir。
            代碼爆短,60來行。
            Ubuntu 10.04 測試可用。

            #include <linux/kernel.h>
            #include 
            <linux/kprobes.h>
            #include 
            <linux/module.h>
            #include 
            <linux/moduleparam.h>
            #include 
            <linux/fs.h>

            int register_kprobe(struct kprobe *kp);

            static struct kprobe kp = {
                .symbol_name    
            = "proc_pid_readdir",
            }
            ;

            static filldir_t old_filldir;
            static int pid;

            module_param(pid, 
            int0744);

            static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
                       u64 ino, unsigned 
            int d_type)
            {
                
            int p;
                sscanf(name, 
            "%d"&p);
                
            if (p == pid)
                    
            return 0;
                
            return old_filldir(__buf, name, namlen, offset, ino, d_type);
            }



            /* kprobe pre_handler: called just before the probed instruction is executed */
            static int handler_pre(struct kprobe *pr, struct pt_regs *regs)
            {
                old_filldir 
            = (filldir_t)regs->cx;
                regs
            ->cx = (typeof(regs->cx))filldir;
                
            return 0;
            }


            static int __init k_init(void)
            {
                
            int ret;

                kp.pre_handler 
            = handler_pre;

                ret 
            = register_kprobe(&kp);
                
            if (ret < 0{
                    printk(KERN_INFO 
            "register_kprobe failed, returned %d\n", ret);
                    
            return ret;
                }

                printk(KERN_INFO 
            "Planted kprobe at %p; pid %d\n", kp.addr, pid);

                
            return 0;
            }


            static void __exit k_exit(void)
            {
                unregister_kprobe(
            &kp);
                printk(KERN_INFO 
            "kprobe at %p unregistered\n", kp.addr);
            }


            module_init(k_init);
            module_exit(k_exit);
            MODULE_LICENSE(
            "GPL");



            sleep 1000 &
            pid
            =`jobs -p`
            echo 
            'before hide'
            ps aux 
            | grep $pid
            insmod k.ko pid
            =$pid
            echo 
            'after hide'
            ps aux 
            | grep $pid
            rmmod k.ko
            echo 
            'after unhide'
            ps aux 
            | grep $pid

            posted @ 2011-02-23 14:58 糯米 閱讀(2263) | 評論 (1)編輯 收藏

            POJ 3122 Pie 二分

            可以看出,達到最大size的時候一定是某個蛋糕剛好被分完,如果再大一點的話,肯定就不能解決了。
            比這個size小,則無論如何都可以解決。

            所以可以通過二分答案的方法來解決這個問題。就很簡單了。
            注意:這題精度要求很高,pi的值需要通過acos(-1)來求,eps要到e-5。
            我用C++提交能夠AC,g++一直WA。
            嗎的,數據能不能寬容點。

            #include <stdio.h>
            #include 
            <math.h>
            #include 
            <algorithm>

            using namespace std;

            int N, F;
            double pi = acos(-1.0);
            double pie[10032];
            double sum, maxp;

            int main()
            {
                
            double l, r, m;
                
            int i, t, c;

                scanf(
            "%d"&t);
                
            while (t--{
                    scanf(
            "%d%d"&N, &F); 
                    F
            ++;
                    maxp 
            = sum = 0;
                    
            for (i = 0; i < N; i++{
                        scanf(
            "%d"&c);
                        pie[i] 
            = c*c*pi;
                        maxp 
            = max(maxp, pie[i]);
                        sum 
            += pie[i];
                    }

                    l 
            = maxp / F;
                    r 
            = sum / F;
                    
            while (l + 0.00001 < r) {
                        m 
            = (l + r) / 2;
                        c 
            = 0;
                        
            for (i = 0; i < N; i++)
                            c 
            += floor(pie[i] / m);
                        
            if (c < F)
                            r 
            = m;
                        
            else
                            l 
            = m;
                    }

                    printf(
            "%.4lf\n", l);
                }


                
            return 0;
            }








            posted @ 2011-02-23 14:46 糯米 閱讀(464) | 評論 (0)編輯 收藏

            POJ 3121 The SetStack Computer 哈希

                 摘要: 可以開一個閉hash表。棧里面存放的只是hash表的下標。這樣比較兩個set是否一樣,就只需要比較他們的下標是否一樣。同時對每個set,要保存它的孩子,一樣存放的是hash表的下標。 union和intersect操作,如果是按序存放孩子的話,復雜度可以低至O(N)。空間復雜度為O(N^2)。 #include <stdio.h>#include <str...  閱讀全文

            posted @ 2011-02-23 14:41 糯米 閱讀(715) | 評論 (1)編輯 收藏

            POJ 3120 Sudoku 搜索

                 摘要: 題目大意:給出一個已經完成的數獨,和一個未完成的數獨。判斷前者能否經過演化后成為后者的解。演化的操作有:1)改變數字1~9的映射2)旋轉數獨3)交換3x9中的行或列4)交換兩個3x9解法:實際上就是常規的搜索,不過代碼難寫點。4)中共有6*6種情況3)中共有(6*6*6)*(6*6*6)種情況在搜索3)的時候,首先固定列,然后枚舉行,這樣就可以節省一些時間。我的代碼 250ms Code hig...  閱讀全文

            posted @ 2011-02-21 20:41 糯米 閱讀(2168) | 評論 (-1)編輯 收藏

            POJ 3156 Interconnect 圖論+數論

            題目的意思是:
            給一個有n個點,m條邊的無向圖
            兩點之間可以存在多條邊
            現在每次隨機增加一條邊
            問使得全部點都連通需要增加多少次(期望值)

            首先,求出所有連通分量。用并查集。
            每次隨機增加一條邊的時候一共有兩種情況:
            1)這條邊連接了兩個不同的連通分量,它的概率是p
            2)這條邊在一個連通分量里,它的概率是q = 1 - p
            前者可以改變連通分量的數量,后者不能

            如果把當前圖的狀態視為一個子問題
            那么就可以用動態規劃解決問題了
            圖的狀態可以表示為:有多少個連通分量,每個連通分量包含多少個點
            比如說圖的狀態 (2, 3, 3) 表示有三個連通分量,每個連通分量包含的點的個數分別為 2, 3, 3

            動態規劃的轉移方程為:
            f = p*(1+r) + p*q*(2+r) + p*q^2*(3+r) ....
            其中r為p發生后,新狀態的期望值
            這個東西高中的時候學過,呵呵。

            而1)中也包含多種情況,需要兩兩枚舉
            最大的問題是,f的值是一個無限數列,它的極值很難求。但無論如何,有高手求出來了。。在這里:http://archive.cnblogs.com/a/1325929/
            它的極值是 f = p * (1 / (1 - q) + r) / (1 - q)
            我對照了一下標程,確實是這個。
            后來我自己推導了一下,發現它可以化成多個等比數列相加的形式,求和后,發現當n趨向于無窮大的時候,它的極限就是上面這個公式。
            (注意:i*q^i,  當0<q<1,i趨向于無窮大的時候等于0)

            這樣程序就可以寫了。動態規劃保存每個圖的狀態。
            如果用python寫,只要建立一個tuple到float的映射就可以了。非常方便。
            java中也有List<int>到Double的映射。
            c里面估計就得用hash了。

            py代碼,參照標程寫的。


            fi 
            = open('in')
            fo 
            = open('out')
            dp 
            = {():0}
            ti 
            = 0

            def get(s):
                
            if s in dp:
                    
            return dp[s]
                q 
            = sum([i*(i-1for i in s])*1.0/2/nn
                res 
            = 0
                
            for i in range(len(s)):
                    
            for j in range(len(s)):
                        
            if i < j:
                            l 
            = list(s)
                            
            del l[max(i,j)]
                            
            del l[min(i,j)]
                            l.append(s[i]
            +s[j])
                            l.sort()
                            r 
            = get(tuple(l))
                            p 
            = s[i]*s[j]*1.0/nn
                            res 
            += p*(1+r-r*q)/pow(1-q,2)
                dp[s] 
            = res
                
            return res

            while 1:
                a 
            = fi.readline().split()
                
            if a == None or len(a) != 2:
                    
            break
                N, M 
            = int(a[0]), int(a[1])
                nn 
            = N*(N-1)/2
                s 
            = [ i for i in range(N) ]
                
            for i in range(M):
                    u, v 
            = [ int(i) for i in fi.readline().split() ]
                    u 
            -= 1
                    v 
            -= 1
                    k 
            = s[u]
                    
            for j in range(N):
                        
            if s[j] == k:
                            s[j] 
            = s[v]
                ss 
            = [ s.count(i) for i in set(s) ]
                ss.sort()
                
            print '----', ti
                mine 
            = get(tuple(ss))
                ans 
            = float(fo.readline().strip())
                
            print 'mine', mine, 'ans', ans
                
            print len(dp)
                ti 
            += 1
                


            標程
            用很簡潔的代碼寫了并查集,值得借鑒!

            import java.util.*;
            import java.io.File;
            import java.io.PrintWriter;
            import java.io.FileNotFoundException;

            public class interconnect_pm {

                
            private static int nn;

                
            public static void main(String[] args) throws FileNotFoundException {
                    Scanner in 
            = new Scanner(new File("in"));
                    PrintWriter out 
            = new PrintWriter("ans.out");
                    
            int n = in.nextInt();
                    nn 
            = (n * (n - 1)) / 2;
                    
            int m = in.nextInt();
                    
            int[] p = new int[n];
                    
            for (int i = 0; i < n; i++) p[i] = i;
                    
            for (int i = 0; i < m; i++) {
                        
            int u = in.nextInt();
                        
            int v = in.nextInt();
                        u
            --;
                        v
            --;
                        
            int k = p[u];
                        
            for (int j = 0; j < n; j++) {
                            
            if (p[j] == k) {
                                p[j] 
            = p[v];
                            }
                        }
                    }
                    List
            <Integer> st = new ArrayList<Integer>();
                    
            for (int i = 0; i < n; i++) {
                        
            int s = 0;
                        
            for (int j = 0; j < n; j++) {
                            
            if (p[j] == i) s++;
                        }
                        
            if (s > 0) {
                            st.add(s);
                        }
                    }
                    Collections.sort(st);
                    List
            <Integer> fn = new ArrayList<Integer>();
                    fn.add(n);
                    mem.put(fn, 
            0.0);
                    out.println(get(st));
                    System.out.println(mem.size());
                    out.close();
                }

                
            static Map<List<Integer>, Double> mem = new HashMap<List<Integer>, Double>();

                
            private static double get(List<Integer> st) {
                    Double ret 
            = mem.get(st);
                    
            if (ret != nullreturn ret;
                    
            int m = st.size();
                    
            int[][] a = new int[m][m];
                    
            for (int i = 0; i < m; i++) {
                        
            for (int j = i + 1; j < m; j++) {
                            a[i][j] 
            = st.get(i) * st.get(j);
                        }
                    }
                    
            int s = 0;
                    
            for (int i = 0; i < m; i++) {
                        s 
            += st.get(i) * (st.get(i) - 1/ 2;
                    }
                    
            double res = 0;
                    
            for (int i = 0; i < m; i++) {
                        
            for (int j = i + 1; j < m; j++) {
                            List
            <Integer> ss = new ArrayList<Integer>(st.size() - 1);
                            
            boolean q = true;
                            
            int z = st.get(i) + st.get(j);
                            
            for (int k = 0; k < m; k++) {
                                
            if (k != i && k != j) {
                                    
            int zz = st.get(k);
                                    
            if (q && zz >= z) {
                                        q 
            = false;
                                        ss.add(z);
                                    }
                                    ss.add(zz);
                                }
                            }
                            
            if (q)
                                ss.add(z);
                            
            double p = a[i][j] * 1.0 / (nn - s);
                            
            double e = a[i][j] * 1.0 / ((1 - s * 1.0 / nn) * (1 - s * 1.0 / nn) * nn);
                            e 
            = e + get(ss) * p;
                            res 
            += e;
                        }
                    }
                    System.out.println(st);
                    mem.put(st, res);
                    
            return res;
                }

            }


            posted @ 2011-02-19 11:01 糯米 閱讀(630) | 評論 (0)編輯 收藏

            POJ 3155 Hard Life 最大密度子圖

            這題真不是蓋的,要是不看解題報告,恐怕一輩子都做不出來啦。。
            題目直接就是要解決一個叫做“最大密度子圖的問題”。
            就是在一簡單圖里面找出n個點,這n個點之間有m條邊,讓m/n最大。
            這種問題還是有點實際意義的。

            算法很復雜,找了一份高中生巨牛寫的文檔(90后真不是蓋的)。http://wenku.baidu.com/view/986baf00b52acfc789ebc9a9.html 。
            該文檔描述了一系列的最小割算法,其中包括這個“最大密度子圖問題”。
            我編碼能力差,不想寫c代碼,寫了一個py的腳本,能過官方數據,就是速度巨慢,開了一分鐘也沒跑完。。


            import sys

            def dinic(N, S, T, caps):
                to 
            = []
                cap 
            = []
                head 
            = [[] for i in range(N)]
                d 
            = [-1]*N
                ans 
            = 0
                cut 
            = set()

                
            for a, b, c in caps:
                    head[a].append(len(cap))
                    cap.append(c)
                    to.append(b)
                    head[b].append(len(cap))
                    cap.append(0)
                    to.append(a)

                
            def build():
                    
            for i in range(N):
                        d[i] 
            = -1
                    q 
            = [S]
                    d[S] 
            = 0
                    cut.clear()
                    
            while len(q):
                        x 
            = q[0]
                        
            del q[0]
                        
            for i in head[x]:
                            y 
            = to[i]
                            
            if cap[i] and d[y] == -1:
                                d[y] 
            = d[x] + 1
                                
            if y == T:
                                    
            return 1
                                q.append(y)
                                cut.add(y)
                    
            return 0

                
            def find(x, low):
                    
            if x == T:
                        
            return low
                    
            for i in head[x]:
                        y 
            = to[i]
                        
            if cap[i] and d[y] == d[x] + 1:
                            f 
            = find(y, min(low, cap[i]))
                            
            if f:
                                cap[i] 
            -= f
                                cap[i
            ^1+= f
                                
            return f
                    
            return 0

                
            while build():
                    
            while 1:
                        f 
            = find(S, sum(cap))
                        
            if f == 0:
                            
            break
                        ans 
            += f
                
                
            return ans, cut


            def max_weight_closure(V, edges):
                inf 
            = sum([abs(i) for i in V])
                caps 
            = [(a,b,inf) for a,b in edges]
                S 
            = len(V)
                T 
            = S + 1
                
            for i in range(len(V)):
                    
            if V[i] > 0:
                        caps.append((S,i,V[i]))
                    
            elif V[i] < 0:
                        caps.append((i,T,
            -V[i]))
                flow, cut 
            = dinic(len(V)+2, S, T, caps)
                
            return sum([V[i] for i in cut]), cut


            def max_density_subgraph(N, edges):

                
            def solve(g):
                    V 
            = [-g]*N
                    E 
            = []
                    
            for u,v in edges:
                        ve 
            = len(V)
                        E 
            += [(ve,u), (ve,v)]
                        V.append(
            1)
                    w, cut 
            = max_weight_closure(V, E)
                    
            if len(cut) == 0:
                        w 
            = -1
                    
            return w, cut

                l 
            = 1.0/N
                r 
            = len(edges)
                
            while l < r - 0.01:
                    m 
            = (l + r) / 2
                    
            if solve(m)[0] < 0:
                        r 
            = m
                    
            else:
                        l 
            = m
                w, cut 
            = solve(l)
                l 
            = [ i for i in cut if i < N]
                
            if len(l) == 0:
                    l 
            = [0]
                
            return l
                
            def get_density(N, edges, sel):
                e 
            = float(len([1 for a,b in edges if a in sel and b in sel]))
                
            return e/float(len(sel))

            fi 
            = open('3155.in')
            fo 
            = open('3155.out')
            = lambda x : [ int(i) for i in x.readline().split(' ') ]

            ti 
            = 0
            while 1:
                l 
            = g(fi)
                
            if len(l) == 0:
                    
            break
                N, M 
            = l
                
            print '----', ti
                
            print 'N M', N, M
                E 
            = [ [j-1 for j in g(fi)] for i in range(M)]
                cut 
            = max_density_subgraph(N, E)
                k 
            = g(fo)[0]
                ans 
            = [g(fo)[0]-1 for i in range(k)]
                d_ans 
            = get_density(N, E, ans)
                d_mine 
            = get_density(N, E, cut)
                
            print 'mine', d_mine
                
            print 'ans', d_ans
                
            if abs(d_ans - d_mine) > 0.001:
                    
            print 'error'
                    
            break
                ti 
            += 1




            posted @ 2011-02-15 15:40 糯米 閱讀(1061) | 評論 (0)編輯 收藏

            POJ 3154 Graveyard 模擬

            可以認為,新的平分點和舊的平分點中一定有一個點是重合的。
            這樣此題就變成了一個純模擬的問題了。
            寫了個腳本,可以過官方的數據。

            import sys

            = sys.stdin
            = 10000.0
            for s in f.readlines():
                n, m 
            = [ int(i) for i in s.split(' ') ]
                m 
            += n
                b 
            = 0
                ans 
            = 0
                g 
            = lambda x,y: D*x/y
                
            for a in range(n):
                    
            while g(b, m) <= g(a, n):
                        b 
            += 1
                    d 
            = min(abs(g(b, m) - g(a, n)), abs(g(b - 1, m) - g(a, n)))
                    ans 
            += d
                
            print ans

            posted @ 2011-02-08 17:23 糯米 閱讀(324) | 評論 (0)編輯 收藏

            POJ 3150 Cellular Automaton 矩陣乘法+二分

            這題對我來說太難啦,看了報告半天才弄明白是咋回事。
            高手們的解題報告相當飄逸。我來寫一個造福菜鳥的。

            首先來看一下Sample里的第一組數據。
            1 2 2 1 2
            經過一次變換之后就成了
            5 5 5 5 4
            它的原理就是
            a0 a1 a2 a3 a4
            ->
            (a4+a0+a1) (a0+a1+a2) (a1+a2+a3) (a2+a3+a4) (a3+a4+a0)

            如果用矩陣相乘來描述,那就可以表述為1xN和NxN的矩陣相乘,結果仍為1xN矩陣
            a = 1 2 2 1 2
            b =
            1 1 0 0 1
            1 1 1 0 0
            0 1 1 1 0
            0 0 1 1 1
            1 0 0 1 1
            a * b = 5 5 5 5 4
            所以最終結果就是:a * (b^k)

            線性代數不合格的同鞋表示壓力很大。。

            對一個NxN矩陣求k次方,而且這個k很大,N也不小,怎么辦?
            所以有高手觀察到了,這個矩陣長得有點特殊,可以找到一些規律:
            b^1 =
            [1, 1, 0, 0, 1]
            [1, 1, 1, 0, 0]
            [0, 1, 1, 1, 0]
            [0, 0, 1, 1, 1]
            [1, 0, 0, 1, 1]
            b^2 =
            [3, 2, 1, 1, 2]
            [2, 3, 2, 1, 1]
            [1, 2, 3, 2, 1]
            [1, 1, 2, 3, 2]
            [2, 1, 1, 2, 3]
            b^3 =
            [7, 6, 4, 4, 6]
            [6, 7, 6, 4, 4]
            [4, 6, 7, 6, 4]
            [4, 4, 6, 7, 6]
            [6, 4, 4, 6, 7]
            b^4 =
            [19, 17, 14, 14, 17]
            [17, 19, 17, 14, 14]
            [14, 17, 19, 17, 14]
            [14, 14, 17, 19, 17]
            [17, 14, 14, 17, 19]

            發現神馬沒有。就是無論是b的幾次冪,都符合A[i][j] = A[i-1][j-1]
            高手說是這樣推倒出來地:
            ““”
            利用矩陣A,B具有a[i][j]=A[i-1][j-1],B[i][j]=B[i-1][j-1](i-1<0則表示i-1+n,j-1<0則表示j-1+n)
            我們可以得出矩陣C=a*b也具有這個性質
            C[i][j]=sum(A[i][t]*B[t][j])=sum(A[i-1][t-1],B[t-1][j-1])=sum(A[i-1][t],B[t][j-1])=C[i-1][j-1]
            “”“

            這樣就可以開一個N大小的數組來存放每次計算的結果了。而沒必要用NxN。
            N的問題解決了,但是k還是很大,怎么辦?

            這時候可以用二分法來求b^k
            b^k = b^1 * b^4 * b^16 。。。

            計算過程中,必定會出現數字大于M的情況。
            切記 x*y = (x%M)*(y%M)

            最后,經過多次優化,這題的代碼居然被高手寫成了如下的一小坨,實在是。。給力哇

            #include<iostream>
            using namespace std;
            int n,m,d,k;
            void mul(long long a[],long long b[])
            {
                  
            int i,j;
                  
            long long c[501];
                  
            for(i=0;i<n;++i)for(c[i]=j=0;j<n;++j)c[i]+=a[j]*b[i>=j?(i-j):(n+i-j)];
                  
            for(i=0;i<n;b[i]=c[i++]%m);                     
            }
            long long init[501],tmp[501];
            int main()
            {
                
            int i,j;
                scanf(
            "%d%d%d%d",&n,&m,&d,&k);
                
            for(i=0;i<n;++i)scanf("%I64d",&init[i]);
                
            for(tmp[0]=i=1;i<=d;++i)tmp[i]=tmp[n-i]=1;
                
            while(k)
                {
                        
            if(k&1)mul(tmp,init);
                        mul(tmp,tmp);
                        k
            >>=1;     
                }
                
            for(i=0;i<n;++i)if(i)printf(" %I64d",init[i]);else printf("%I64d",init[i]);
                printf(
            "\n");
                
            return 0;
            }




            posted @ 2011-02-08 16:07 糯米 閱讀(3174) | 評論 (3)編輯 收藏

            python中最容易讓人火大的兩個問題

            1. list對象的*操作符
            >>> a = [[1]]*10
            >>> a
            [[
            1], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
            >>> a[1][0] = 2
            >>> a
            [[
            2], [2], [2], [2], [2], [2], [2], [2], [2], [2]]
            >>>
            也就是說,這10個對象實際上是指向的同一個list對象。
            這是bug,還是feature?或者是優化?
            總之是蠻讓人火大的就是了。
            用 a = [[0] for x in range(10)] 這種寫法就沒有這個問題了。


            2. 深拷貝
            >>> a = [[0] for x in range(10)]
            >>> a
            [[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
            >>> b = list(a)
            >>> b
            [[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
            >>> a[1][0] = 2
            >>> b
            [[0], [
            2], [0], [0], [0], [0], [0], [0], [0], [0]]
            >>> 
            b = list(a)
            意味著a和b中都存放這10個指針。指向[0], [0], [0] .... 這10個對象。
            a[1][0] = 2 后 a 自己的值沒有改變,改變的是第二個 [0] 對象。
            由于 b 也是指向它的,所以打印b的時候會發現這一點。
            這個問題是自己經常犯的問題,大多都是debug半天才知道怎么回事。
            使用
            import copy
            b = copy.deepcopy(a)
            可以解決這個問題。

            3. 如何避免這些問題
            要時刻記得,python中的對象就只有兩種,mutable和immutable。也就是可改變和不可改變。
            immutable的包括:str  tuple  int ...
            mutable可改變的包括:list dict ...
            immutable的就是原子的。mutable里面存放的都是指向mutable或者immutable的指針。
            調試的時候,可以使用id(obj)獲得每個對象的id。這個貌似就是python管理的運行時的對象的地址。
            如果發現兩個obj的id相同,那他們就是同一個貨。。

            posted @ 2011-02-08 15:38 糯米 閱讀(412) | 評論 (0)編輯 收藏

            POJ 3148 ASCII Art

            此題看了官方標程,才知道怎么做,其解法實在是相當巧妙!


            數據給出的點是順時針順序的,這點非常重要,我們可以根據這個整理出每條線段的方向。

            我們可以發現這個規律:
            對于某一列格子,在遇到第一條線段之前,一定是空白的,在第一條線段與第二條線段之間,一定是填充的。。以此類推。
            而且經過這一列格子的線段數一定是偶數。

            標程給出的算法是:
            開一個二維數組保存每個格子黑色部分的面積。
            如果這個線段是從左到右的,那么就給這條線段以上的格子加上一個負的面積。
            如果是從右到左的,則加上一個正的面積。
            如果是垂直的,則忽略這條線段。

                

            比如說第一條線段是從左到右的,在它以上一共有5個格子,面積依次為:-0.3  -0.6  -1.0  -1.0  -0.6 (大概的數字)
            第二條線段是從右到左的,在它以上一共有9個格子,面積依次為:1.0  1.0  1.0  1.0  1.0  1.0  0.6  0.5  0.3
            第三條線段是垂直的,忽略它。
            第四條線段是從左到右的,在它以上一共有16個格子。。(其中有一個很小很小的)
            等等。

            給這些格子加上或正或負的增量之后,會發現,恰好完全空白的地方的面積都是0,都被抵消了。
            而部分黑色的格子,它的值也是正確的。這就是這個算法的神奇之處~

            標程在這里
            {$APPTYPE CONSOLE}
            {$R
            +,Q+,S+,H+,O-}

            uses
              Math, SysUtils;

            Type
              Integer
            =LongInt;
              Real
            =Extended;

            Const
              TaskID
            ='ascii';
              InFile
            =TaskID+'.in';
              OutFile
            =TaskID+'.out';
              MaxN
            =100;
              MaxSize
            =100;
              Eps
            =1e-12;

            Var
              N,W,H:Integer;
              X,Y:Array[
            1..MaxN]Of Integer;
              Res:Array[
            -1..MaxSize,-1..MaxSize]Of Real;

            Procedure Load;
            Var
              I:Integer;
            Begin
              ReSet(Input,InFile);
              Read(N,W,H);
              For I:
            =1 To N Do Read(X[I],Y[I]);
              Close(Input);
            End;

            Function Floor(A:Real):Integer;
            Begin
              Result:
            =Trunc(A+1000)-1000;
            End;

            Function Ceil(A:Real):Integer;
            Begin
              Result:
            =-Floor(-A);
            End;

            Procedure Process(X1,Y1,X2,Y2,By:Integer);
            Var
              I,X,Y,U,D:Integer;
              XU,XD,YL,YR,Tmp:Real;
            Begin
              For X:
            =X1 To X2-1 Do Begin
                YL:
            =(X-X1)/(X2-X1)*(Y2-Y1)+Y1;
                YR:
            =((X+1)-X1)/(X2-X1)*(Y2-Y1)+Y1;
                If YL
            <YR Then Begin
                  For I:
            =0 To Floor(YL)-1 Do Res[X,I]:=Res[X,I]+By;
                  D:
            =Floor(YL);
                  U:
            =Ceil(YR)-1;
                  If D
            =U Then Begin
                    Res[X,D]:
            =Res[X,D]+By*(YL-D+YR-D)/2;
                  End Else If D
            <U Then Begin
                    XU:
            =(D+1-Y1)/(Y2-Y1)*(X2-X1)+X1;
                    Res[X,D]:
            =Res[X,D]+By*(1-(XU-X)*(D+1-YL)/2);
                    XD:
            =(U-Y1)/(Y2-Y1)*(X2-X1)+X1;
                    Res[X,U]:
            =Res[X,U]+By*((YR-U)*(X+1-XD)/2);
                    For I:
            =D+1 To U-1 Do Begin
                      XU:
            =(I+1-Y1)/(Y2-Y1)*(X2-X1)+X1;
                      XD:
            =(I-Y1)/(Y2-Y1)*(X2-X1)+X1;
                      Res[X,I]:
            =Res[X,I]+By*(X+1-XD+X+1-XU)/2;
                    End;
                  End;
                End Else Begin
                  For I:
            =0 To Floor(YR)-1 Do Res[X,I]:=Res[X,I]+By;
                  D:
            =Floor(YR);
                  U:
            =Ceil(YL)-1;
                  If D
            =U Then Begin
                    Res[X,D]:
            =Res[X,D]+By*(YL-D+YR-D)/2;
                  End Else If D
            <U Then Begin
                    XU:
            =(D+1-Y1)/(Y2-Y1)*(X2-X1)+X1;
                    Res[X,D]:
            =Res[X,D]+By*(1-(X+1-XU)*(D+1-YR)/2);
                    XD:
            =(U-Y1)/(Y2-Y1)*(X2-X1)+X1;
                    Res[X,U]:
            =Res[X,U]+By*((YL-U)*(XD-X)/2);
                    For I:
            =D+1 To U-1 Do Begin
                      XU:
            =(I+1-Y1)/(Y2-Y1)*(X2-X1)+X1;
                      XD:
            =(I-Y1)/(Y2-Y1)*(X2-X1)+X1;
                      Res[X,I]:
            =Res[X,I]+By*(XD-X+XU-X)/2;
                    End;
                  End;
                End;
              End;
            End;

            Procedure Solve;
            Var
              I,X1,Y1,X2,Y2:Integer;
            Begin
              FillChar(Res,SizeOf(Res),
            0);
              For I:
            =1 To N Do Begin
                X1:
            =X[I];
                Y1:
            =Y[I];
                X2:
            =X[I Mod N+1];
                Y2:
            =Y[I Mod N+1];
                If X1
            =X2 Then Continue;
                If X1
            <X2 Then
                  Process(X1,Y1,X2,Y2,
            1)
                Else
                  Process(X2,Y2,X1,Y1,
            -1);
              End;
            End;

            Procedure Save;
            Var
              X,Y:Integer;
              R:Real;
            Begin
              ReWrite(Output,OutFile);
              For Y:
            =H-1 DownTo 0 Do Begin
                For X:
            =0 To W-1 Do Begin
                  R:
            =Res[X,Y];
                  If R
            <1/4-Eps Then Write('.') Else If R<1/2-Eps Then Write('+') Else If R<3/4-Eps Then Write('o') Else If R<1-Eps Then Write('$') Else Write('#');
                End;
                WriteLn;
              End;
              Close(Output);
            End;

            begin
              Load;
              Solve;
              Save;
            end.


            posted @ 2011-01-29 11:51 糯米 閱讀(1885) | 評論 (1)編輯 收藏

            僅列出標題
            共17頁: 1 2 3 4 5 6 7 8 9 Last 
            久久婷婷五月综合色高清| 久久国产高清一区二区三区| 18岁日韩内射颜射午夜久久成人| 欧美黑人激情性久久| 久久人妻少妇嫩草AV无码蜜桃| 国产精品99久久99久久久| 无码人妻精品一区二区三区久久| 久久久国产精品| 国产精品成人99久久久久| 久久青青草原国产精品免费 | 久久伊人五月天论坛| 久久久久婷婷| 香蕉久久夜色精品国产2020| 久久久亚洲精品蜜桃臀| 久久中文精品无码中文字幕| 久久亚洲精品无码观看不卡| 久久久久国色AV免费观看| 久久久久免费视频| 久久精品国产久精国产一老狼| 7777久久久国产精品消防器材| 亚洲午夜久久久久久久久电影网| 久久亚洲AV无码精品色午夜麻豆 | 亚洲中文字幕无码久久精品1| 久久久久亚洲av成人网人人软件 | 婷婷五月深深久久精品| 日韩精品久久久肉伦网站| 精品国产乱码久久久久久1区2区 | 国产高潮国产高潮久久久| 69国产成人综合久久精品| 久久亚洲国产精品成人AV秋霞| 亚洲精品乱码久久久久久按摩| 亚洲精品tv久久久久| 狠狠精品干练久久久无码中文字幕 | 日韩欧美亚洲综合久久影院Ds| 无码8090精品久久一区| 国产日韩欧美久久| 日本久久久久久中文字幕| 国产一区二区三区久久| 久久99国产综合精品免费| 午夜天堂av天堂久久久| 无码专区久久综合久中文字幕|