• <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>

            oyjpArt ACM/ICPC算法程序設(shè)計(jì)空間

            // I am new in programming, welcome to my blog
            I am oyjpart(alpc12, 四城)
            posts - 224, comments - 694, trackbacks - 0, articles - 6

            說題

            Posted on 2008-08-02 16:05 oyjpart 閱讀(3231) 評(píng)論(3)  編輯 收藏 引用 所屬分類: ACM/ICPC或其他比賽
            PKU3034 Whac-a-Mole
            很有意思的題目,打地鼠。
            簡(jiǎn)單的記憶化搜索。trick在于你有可能移出地鼠區(qū),形成一個(gè)更優(yōu)的解。

            PKU2280 Amphiphilic Carbon Molecules
            首先可以證明要求的線一定由兩點(diǎn)確定。
            基本算法:枚舉點(diǎn)+極角序+一圈掃描。
            難點(diǎn)1:計(jì)較排序
            難點(diǎn)2:一圈掃描時(shí)候的計(jì)數(shù)。
            巧妙的轉(zhuǎn)化:枚舉一個(gè)點(diǎn)x之后將所有的黑點(diǎn)移到關(guān)于x的對(duì)稱點(diǎn)上,這樣題目就轉(zhuǎn)化成了:
            求一條線,這條線上和這條線的一側(cè)的點(diǎn)的和最大。簡(jiǎn)單多了。
            這是去年省賽A題,當(dāng)時(shí)就是用這種方法AC的。
            // Solution by alpc12
            #include 
            <algorithm>
            #include 
            <math.h>
            using namespace std;

            #define Max(a,b)((a)>(b)?(a):(b))

            struct Point{
                
            int x, y;
                
            bool mk;
                
                
            bool operator < (const Point &a) const{
                    
            if (y >= 0 && a.y < 0return true;
                    
            else if (y < 0 && a.y >= 0return false;
                    
            if (y == 0 && a.y == 0){
                        
            if (x >= 0 && a.x < 0return true;
                        
            if (x < 0 && a.x >= 0return false;
                        
            return abs(x) < abs(a.x); 
                    }
                    
            int t = x * a.y - y * a.x;
                    
            return  t == 0 ? x*+ y*< a.x*a.x + a.y*a.y : t > 0;
                };

            } p[
            1010], pp[1010];

            int n;
            int nn;
            int ans;

            int det(Point &a, Point &b){
                
            return a.x * b.y - a.y * b.x;
            }

            int dot(Point &a, Point &b){
                
            return a.x * b.x + a.y * b.y;
            }

            void solve(int x){
                
            //printf("Center %d (%d, %d)\n", x, p[x].x, p[x].y);
                nn = 0;
                
            int i;
                
            for (i = 0; i < n; i++if (i != x){
                    pp[nn].x 
            = p[i].x - p[x].x;
                    pp[nn].y 
            = p[i].y - p[x].y;
                    pp[nn].mk 
            = p[i].mk;
                    
            if(pp[nn].mk) pp[nn].x = -pp[nn].x, pp[nn].y = -pp[nn].y;
                    nn
            ++;
                }
                sort(pp, pp 
            + nn);
                
            int a = 0, b = 0, cnt = 0;
                
            for(i = 0; i < nn; ++i) {
                    
            if(det(pp[a], pp[i]) >= 0) {
                        b 
            = i;
                        cnt
            ++;
                    } 
                }
                ans 
            = Max(ans, cnt);
                
            while(1) {
                    
            int aa = a;
                    
            for(; det(pp[aa], pp[a]) == 0 && dot(pp[aa], pp[a]) >= 0 && aa < nn; ++aa) {
                        cnt
            --;
                    }
                    
            if(aa == nn) break;
                    a 
            = aa;
                    
            int bb = (b+1)%nn;
                    
            for(; det(pp[aa], pp[bb]) >= 0; bb = (bb+1)%nn) {
                        cnt
            ++;
                        b 
            = bb;
                    }
                    ans 
            = Max(ans,cnt);
                }
            }

            int main(){

                
            //freopen("t.in", "r", stdin);

                
            while (scanf("%d"&n), n){
                    
            int t, i;
                    
            for (i = 0; i < n; i++){
                        scanf(
            "%d%d%d"&p[i].x, &p[i].y, &t);
                        p[i].mk 
            = (t == 1);
                    }
                    
            if (n == 1) {printf("1\n"); continue;}
                    ans 
            = 0;
                    
            for (i = 0; i < n; i++)
                        solve(i);
                    printf(
            "%d\n", ans + 1);
                }
                
            return 0;   
            }

            PKU2949 Word Rings
            經(jīng)典題。
            首先將輸入的單詞看成一條邊。它連接的左右各2字符形成的點(diǎn)。
            那么新的圖點(diǎn)為26*26個(gè)。
            然后二分枚舉答案ans,將原來的圖的權(quán)w轉(zhuǎn)化為ans-w,
            用Bellman Ford判負(fù)權(quán)回路。如果有負(fù)權(quán)回路,說明
            sigma(ans) + sigma(w) < 0
            即 ans * cycle_length < sigma(w)
            sigma(w)是原本的單詞長(zhǎng)度和,而ans * cycle_length則是枚舉答案之后那個(gè)環(huán)的單詞長(zhǎng)度和
            所以 ans 可以繼續(xù)增大。 這樣就構(gòu)成了二分。
            // Solution by alpc12
            #include <stdio.h>
            #include 
            <string.h>

            #define Max(a,b) ((a)>(b)?(a):(b))

            const int M = 200020;
            const int N = 26*26;

            struct Edge
            {
                
            int x, y;
                
            double w;
                Edge() {}
                Edge(
            int xx, int yy, double ww) : x(xx), y(yy), w(ww) {
                }
            };

            int n, m, nv;
            Edge e[M];
            double dist[N];

            bool bellman_ford(double ans) {
                
            int i,j;
                
            for(i = 0; i < nv; ++i) {
                    
            bool change = false;
                    
            for(j = 0; j < m; ++j) {
                        
            int &x= e[j].x, &= e[j].y;
                        
            double w = e[j].w;
                        
            if(dist[y] > dist[x] + ans - w) {
                            change 
            = true;
                            dist[y] 
            = dist[x] + ans - w;
                        }
                    }
                    
            if(!change) return true;
                }
                
            return false;
            }

            int calc(char a, char b) {
                
            return (a-'a'* 26 + b-'a';
            }

            int main()
            {
                freopen(
            "t.in""r", stdin);

                
            char line[1010];
                
            int i, max;
                
            bool chk[N];
                
            while(scanf("%d\n"&n), n) {
                    memset(chk, 
            0sizeof(chk));
                    m 
            = nv = 0;
                    
            for(i = 0; i < n; ++i) {
                        gets(line);
                        
            int len;
                        
            if((len=strlen(line)) <= 2while(1) printf("1");
                        max 
            = Max(max, len);
                        
            int a = calc(line[0], line[1]), b = calc(line[len-2], line[len-1]);
                        
            if(!chk[a]) chk[a] = 1, nv++
                        
            if(!chk[b]) chk[b] = 1, nv++;
                        e[m
            ++= Edge(a,b,(double)len);
                    }


                    
            double lo = 0, hi = max;
                    
            while(hi > lo + 0.005) {
                        
            double mid = lo+(hi-lo)/2;
                        
            if(!bellman_ford(mid)) {
                            lo 
            = mid;
                        } 
            else hi = mid;
                    }
                    
            if(lo < 1e-7) printf("No solution.\n");
                    
            else printf("%.2lf\n", lo);
                }

                
            return 0;
            }


            PKU2793 Cactus
            這個(gè)題目的要求:
            1.求一個(gè)圖所有的環(huán)的長(zhǎng)度
            2.判斷一個(gè)圖中任意兩個(gè)環(huán)是否共邊
            3.判斷一個(gè)圖是否連通

            一個(gè)圖的環(huán)的求法(DFS):
            若現(xiàn)在在dfs 節(jié)點(diǎn)x,其子節(jié)點(diǎn)y是一個(gè)灰色節(jié)點(diǎn)(已經(jīng)遍歷到,但子樹沒有遍歷完的節(jié)點(diǎn)),那么就存在一個(gè)x->y->...->x的環(huán)。從x向上找一直到y(tǒng)就是環(huán)了。
            // solution by alpc12 
            // 注意這個(gè)代碼在pku上會(huì)runtime error,棧溢出。
            // 因?yàn)閖ava的棧空間很小。
            import java.io.BufferedReader;
            import java.io.FileNotFoundException;
            import java.io.FileOutputStream;
            import java.io.FileReader;
            import java.io.FileWriter;
            import java.io.PrintStream;
            import java.io.PrintWriter;
            import java.math.BigInteger;
            import java.util.ArrayList;
            import java.util.Arrays;
            import java.util.Scanner;

            public class Main {
                
            int n;

                final 
            int N = 20010;
                
                
            private class Edge {
                    
            int x, y;
                    
            public boolean inCycle;
                    
            int other(int z) {
                        
            return x == z ? y : x;
                    }
                    
            public Edge(int x, int y) {
                        super();
                        
            this.x = x;
                        
            this.y = y;
                        inCycle 
            = false;
                    }
                }

                ArrayList
            <Edge>[] head = new ArrayList[N];
                
                Edge[] fa 
            = new Edge[N]; 

                
            int[] chk = new int[N];

                ArrayList
            <Integer> Clen = new ArrayList<Integer>();
                
                BigInteger Ans 
            = BigInteger.ONE;

                boolean hasSol;
                
                PrintStream 
            out

                
            void run() throws FileNotFoundException {
                    
            //Scanner cin = new Scanner(System.in);
                    Scanner cin = new Scanner(new BufferedReader(new FileReader("43")));
                    
            out = System.out;
                    
            int m;
                    n 
            = cin.nextInt();
                    
            for (int i = 0; i < n; ++i) {
                        head[i] 
            = new ArrayList<Edge>();
                    }
                    m 
            = cin.nextInt();
                    
            while (m-- != 0) {
                        
            int c = cin.nextInt();
                        ArrayList
            <Integer> ar = new ArrayList<Integer>();
                        
            for (int i = 0; i < c; ++i) {
                            
            int x = cin.nextInt();
                            ar.add(x);
                        }
                        
            for (int i = 0; i < ar.size() - 1++i) {
                            
            int x = ar.get(i) - 1, y = ar.get(i + 1- 1;
                            head[x].add(
            new Edge(x, y));
                            head[y].add(
            new Edge(y, x));
                        }
                    }

                    Arrays.fill(chk, 
            0);
                    hasSol 
            = true;
                    dfs(
            0new Edge(00));
                    
            int i;
                    
            for(i = 0; i < n; ++i) {
                        
            if(chk[i] == 0break;
                    }
                    
            if (i < n || !hasSol) {
                        
            out.println("0");
                        
            return;
                    }
                    
            out.println(Ans);
                }

                
            private void dfs(int x, Edge e) {
                    fa[x] 
            = e;
                    
                    
            int i;
                    chk[x] 
            = 1;
                    
            for(i = 0; i < head[x].size(); ++i) {
                        
            int y = head[x].get(i).y;
                        
            if(chk[y] == 0) {
                            dfs(y, head[x].
            get(i));
                        } 
            else if(chk[y] == 1 && y != e.other(x)){ // y is a ance of x
                            hasSol &= !head[x].get(i).inCycle;
                            head[x].
            get(i).inCycle = true;
                            
            int c = 2;
                            
            for(int j = x; j != y; j = fa[j].other(j)) {
                                hasSol 
            &= !fa[j].inCycle;
                                fa[j].inCycle 
            = true;
                                c
            ++;
                            }
                            Ans 
            = Ans.multiply(new BigInteger("" + c));
                        }
                    }
                    chk[x] 
            = 2;
                }

                
            private boolean conn() {
                    
            int i;
                    Arrays.fill(chk, 
            0);
                    dfs0(
            0);
                    
            for (i = 0; i < n && chk[i] == 1++i);
                    
            return i == n;
                }

                
            private void dfs0(int x) {
                    
            int i;
                    chk[x] 
            = 1;
                    
            for (i = 0; i < head[x].size(); ++i) {
                        
            if (chk[head[x].get(i).y] == 0) {
                            dfs0(head[x].
            get(i).y);
                        }
                    }
                }

                
            public static void main(String[] args) throws FileNotFoundException {
                    
            new Main().run();
                }

            }

            PKU2117 Electricity
            求一個(gè)圖(可能非聯(lián)通)去掉一個(gè)點(diǎn)之后最多的連通塊數(shù)。
            做法:dfs求割。
            在dfs中一個(gè)點(diǎn)x,有子節(jié)點(diǎn)y1,y2...yN.
            比如y1的這棵子樹沒有一個(gè)點(diǎn)能夠有邊連到比x更淺層的點(diǎn),那么y1這棵子樹在去掉x點(diǎn)之后會(huì)是一個(gè)獨(dú)立的聯(lián)通塊。同樣的對(duì)于y2...yN.
            要注意的地方:
            1.單點(diǎn)。去掉個(gè)單點(diǎn)這個(gè)單點(diǎn)聯(lián)通塊就不存在了,聯(lián)通塊數(shù)量會(huì)減少
            2.dfs求割的時(shí)候有根和非根兩種情況,兩種情況分成的聯(lián)通塊是不同的。           

            Feedback

            # re: 說題  回復(fù)  更多評(píng)論   

            2008-08-11 22:20 by Leon916
            又來你的blog看答案了!

            我發(fā)現(xiàn)在里面的題不好做,就是想不出來改怎么做!
            請(qǐng)教一下你平時(shí)怎么練習(xí)的?

            # re: 說題  回復(fù)  更多評(píng)論   

            2008-08-12 10:09 by oyjpart
            現(xiàn)在暑假都是做比賽,這些題目都是比賽的題目。
            比賽可以在TJU(http://acm.tju.edu.cn)上自己帖,很方便的。

            # re: 說題  回復(fù)  更多評(píng)論   

            2008-10-16 20:18 by lxc0601
            大牛,能講解下 PKU2117 Electricity ?
            午夜天堂av天堂久久久| 久久精品国产99国产精品亚洲| 久久久青草久久久青草| 久久国产免费直播| 久久伊人精品青青草原高清| 亚洲午夜久久久久久久久久 | 久久精品亚洲乱码伦伦中文| 精品熟女少妇a∨免费久久| 欧美一区二区久久精品| 色婷婷狠狠久久综合五月| 亚洲精品国产美女久久久| 一本一道久久综合狠狠老| 亚洲Av无码国产情品久久| 精品久久久久久无码不卡| 久久精品99久久香蕉国产色戒| 欧美午夜A∨大片久久| 热久久这里只有精品| 国产激情久久久久影院小草| 亚洲精品无码久久不卡| 日本精品久久久久中文字幕| 久久精品蜜芽亚洲国产AV| 少妇精品久久久一区二区三区| 亚洲精品乱码久久久久久自慰| 久久久无码人妻精品无码| 国产精品免费久久久久久久久| 日产精品久久久久久久性色| 欧美精品一区二区久久| 成人国内精品久久久久一区| 国产成人无码久久久精品一| 久久99精品久久久大学生| 久久精品无码午夜福利理论片 | 久久婷婷人人澡人人爽人人爱| 精品国产乱码久久久久久1区2区 | 四虎久久影院| 成人亚洲欧美久久久久| 青青国产成人久久91网| 国产精品欧美久久久久无广告 | 久久久久久久亚洲精品| 久久精品无码一区二区三区免费 | 亚洲精品无码久久久久久| 国产精品久久久久久福利69堂|