• <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è)計空間

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

            說題~

            Posted on 2007-09-18 17:00 oyjpart 閱讀(2015) 評論(6)  編輯 收藏 引用 所屬分類: ACM/ICPC或其他比賽
            pku2380 Balancing the Scale
            上海的題。看到這題我立刻想到了以前做過的一道:sumset。用類似的方法,可以把任意4個數(shù)連接起來作為一個整體。然后分別放到兩個數(shù)組中,排序。之后從左到右分別檢驗左右是否相等(具體參考程序),注意使用位運算壓縮。
             1#include <string.h>
             2#include <algorithm>
             3#include <stdio.h>
             4
             5using namespace std;
             6
             7#define two(x) (1<<(x))
             8#define contain(S, x) (((S)&(two(x))) != 0)
             9
            10const int MAX = 43680;
            11
            12struct Node {
            13    int mask, w;
            14    Node() {}
            15    Node(int mm, int ww) {
            16        mask = mm;
            17        w = ww;
            18    }

            19}
            A[MAX];
            20
            21int cnt[two(16)];
            22
            23bool operator<(const Node& a, const Node& b) {
            24    return a.w < b.w;
            25}

            26
            27int a[16], nA;
            28
            29void solve() {
            30    int beg = 0, end = 0, i, j, k;
            31    for(i = 1; i < nA; ++i) {
            32        if(A[i].w != A[i-1].w) {
            33            for(j = beg; j <= end; ++j)
            34                for(k = j+1; k <= end; ++k)
            35                    if((A[j].mask&A[k].mask) == 0)
            36                        cnt[A[j].mask|A[k].mask]++;
            37            beg = end = i;
            38        }

            39        else
            40            end = i;
            41    }

            42    int ans = 0;
            43    for(i = 0; i < two(16); ++i) {
            44        if(cnt[i] != 0 && cnt[(two(16)-1)^i] != 0)
            45            ans += cnt[i] * cnt[(two(16)-1)^i];
            46    }

            47    printf("%d\n", ans/2);
            48}

            49
            50int main() {
            51
            52//    freopen("t.in", "r", stdin);
            53
            54    int i, j, k, m, tc = 0;
            55    for(tc = 1; ; tc++{
            56        scanf("%d"&a[0]);
            57        if(a[0== 0
            58            break;
            59        for(i = 1; i < 16++i)
            60            scanf("%d", a+i);
            61        nA = 0;
            62        for(i = 0; i < 16++i)
            63            for(j = 0; j < 16++j) if(j != i) 
            64                for(k = 0; k < 16++k) if(k != i && k != j) 
            65                    for(m = 0; m < 16++m) if(m != i && m != j && m != k) {
            66                        int t = two(i)+two(j)+two(k)+two(m);
            67                        A[nA++= Node(t, 4*a[i]+3*a[j]+2*a[k]+a[m]);
            68                    }

            69        sort(A, A+nA);
            70
            71        memset(cnt, 0, sizeof(cnt));
            72        printf("Case %d: ", tc);
            73        solve();
            74        
            75    }

            76
            77    return 0;
            78}

            79
            80
            81
            82

            PKU1637 Sightseeing tour
            老題了,混合圖的歐拉回路。
            首先是預(yù)判,然后建圖。我的建圖方法是這樣的:
            對于每個點都有自己的入度需求量,將其作為到T的容量。
            對于每個無向邊看一個點,都可以提供1的入度,所以連接S的1容量的邊。
            最后把無向邊連向其能夠提供入度的2個點。

            PKU1848 Tree
            很好的樹形DP,由于題目不允許兩點之間連第3邊(題目沒說-_-|||) 所以要3個狀態(tài)才能搞定。

            PKU3042 Grazing on the Run
            類似于 PKU2671 Jimmy's Bad Day
            很好的區(qū)間DP模型。關(guān)鍵代碼如下
             1
             2    dp[0][n-1][0= dp[0][n-1][1= 0;
             3
             4    for(i = n-1; i >= 1--i) {
             5        for(j = 0; j + i - 1 <= n-1++j) {
             6            k = j+i-1;
             7            if( Beg >= j && Beg <= k ) {
             8                if(j > 0{
             9                    dp[j][k][0= Min(dp[j][k][0], dp[j-1][k][0+ (a[j]-a[j-1])*(j+n-1-k));
            10                    dp[j][k][1= Min(dp[j][k][1], dp[j-1][k][0+ (a[k]-a[j-1])*(j+n-1-k));
            11                }

            12                if(k < n-1{
            13                    dp[j][k][0= Min(dp[j][k][0], dp[j][k+1][1+ (a[k+1]-a[j])*(j+n-1-k));
            14                    dp[j][k][1= Min(dp[j][k][1], dp[j][k+1][1+ (a[k+1]-a[k])*(j+n-1-k));
            15                }

            16//                for(int l = 0; l < 2; ++l)            printf("dp[%d][%d][%d] = %d\n", j, k, l, dp[j][k][l]);
            17            }

            18        }

            19    }

            20

            PKU2795 Exploring Pyramids
            DP。用到了樹形DP的思想(算是吧?)
            關(guān)鍵代碼如下: 
             1        for(i = 0; i < len; ++i)
             2            dp[i][i] = 1;
             3
             4        for(l = 3; l <= len; l += 2{
             5            for(i = 0; i+l-1<=len-1++i) {
             6                j = i+l-1;
             7                dp[i][j] = 0;
             8                if(s[i] == s[j]) {
             9                    for(k = i+2; k <= j; k+=2{
            10                        dp[i][j] = (int)((dp[i][j] + (long long)dp[i+1][k-1* dp[k][j])%MAX); 
            11                    }

            12//                    printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
            13                }

            14            }

            15        }

            16


            PKU3111 K Best
            好題。
            看到了之后,會想到這個和曾經(jīng)一道最有比率生成樹非常相似。用類似的方法進行二分求解是正途。但是到這里還是復(fù)雜度太高(二分里面有一個排序),考慮到只要排序出前K個元素,可以考慮部分排序(用的是快排的原理)。

            PKU1932 XYZZY
            bellman_Ford求負(fù)權(quán)最短路, 當(dāng)有負(fù)權(quán)圈的時候可以檢測到.
            對于這道題而言,我們可以建模為:
            加HP: 負(fù)權(quán)點
            減HP: 正權(quán)點
            將點權(quán)化作邊權(quán)后(可以拆點,或者直接將點權(quán)加入入邊)run一次bellman_ford
            bellman_ford中只擴展標(biāo)號<100的點
            如果無負(fù)權(quán)圈,顯然只需判終點的最短路是否<100
            如果有負(fù)權(quán)圈,就判bellman_ford是否可能到達任何一個負(fù)權(quán)圈上的點.


            PKU3411 Paid Roads
            初看像狀態(tài)壓縮DP,寫完之后才發(fā)現(xiàn)有環(huán)。
            其實只需要拆點轉(zhuǎn)化成最短路模型就可以了。

            Feedback

            # re: 說題~  回復(fù)  更多評論   

            2007-11-11 00:29 by comiz
            我看了很久你第一題的代碼,感覺你的SOLVE函數(shù)前面的比較部分是哪里錯了

            # re: 說題~  回復(fù)  更多評論   

            2007-11-11 13:17 by oyjpart
            那你覺得怎么寫呢?

            # re: 說題~  回復(fù)  更多評論   

            2007-11-11 19:01 by comiz
            我參照的你的思想,用c#寫的
            private void solve()
            {
            int count=0,n=0;
            for(int i=0;i<43680;i+=24)
            for(int j=i+24;j<43680;j+=24)
            if((A[i].flag&A[j].flag)==0)
            for(int k=0;k<24;k++)
            for(int l=0;l<24;l++)
            if(A[i+k].result==A[j+l].result)
            No[A[i+k].flag|A[j+l].flag]++;

            for(count=0;count<two(16);count++)
            if(No[count]!=0&&No[(two(16)-1)^count]!=0)
            {
            n+=No[count]*No[(two(16)-1)^count];
            }
            Console.WriteLine("count:"+(n/2).ToString());

            }
            我剛剛學(xué)算法,可能是我沒有充分理解你寫的吧.另外我十分佩服你!

            # re: 說題~  回復(fù)  更多評論   

            2007-11-11 23:19 by oyjpart
            請問你的24是什么?
            還有你的循環(huán)是43680*43680*24*24的,不出意外的話就超時了:)

            # re: 說題~[未登錄]  回復(fù)  更多評論   

            2007-11-15 22:02 by comiz
            24是因為之前排過序了,出現(xiàn)四個1位置相同的情況肯定是4!種,如果使用了相同的數(shù)就跳過,理論上是要計算43680*43680次,但是我也沒測試過有沒有超時,你能不能現(xiàn)把你寫的意思告訴我?

            # re: 說題~[未登錄]  回復(fù)  更多評論   

            2007-11-16 19:50 by oyjpArt
            29void solve() {
            30 int beg = 0, end = 0, i, j, k;
            31 for(i = 1; i < nA; ++i) {
            32 if(A[i].w != A[i-1].w) { //某一個相同w的段
            33 for(j = beg; j <= end; ++j) //段的開始何結(jié)束的2重枚舉
            34 for(k = j+1; k <= end; ++k)
            35 if((A[j].mask&A[k].mask) == 0) //如果沒有相同的數(shù)
            36 cnt[A[j].mask|A[k].mask]++; //計數(shù)器增加
            37 beg = end = i;
            38 }
            39 else
            40 end = i;
            41 }
            42 int ans = 0;
            43 for(i = 0; i < two(16); ++i) {
            44 if(cnt[i] != 0 && cnt[(two(16)-1)^i] != 0) //如果某些數(shù)字的集合的計數(shù)>0 并且他的補集也>0,就是都用上了
            45 ans += cnt[i] * cnt[(two(16)-1)^i];
            46 }
            47 printf("%d\n", ans/2);
            48}
            99国产精品久久| 国产巨作麻豆欧美亚洲综合久久| 久久婷婷色综合一区二区| 久久久国产精华液| 久久99精品国产99久久| 久久久久亚洲AV综合波多野结衣| 99久久精品免费看国产一区二区三区 | 亚洲伊人久久成综合人影院 | 2021精品国产综合久久| 精品久久久久久无码国产| 中文字幕久久久久人妻| 91久久国产视频| 伊人久久综合成人网| 久久精品国产亚洲精品| 久久精品中文无码资源站| 麻豆久久| 99久久国产热无码精品免费久久久久 | 国产精品久久久久久| 中文字幕无码久久久| 国产精品久久久久天天影视| 午夜视频久久久久一区 | 亚洲精品tv久久久久久久久| 91精品国产91久久久久久| 99国产欧美久久久精品蜜芽| 久久久一本精品99久久精品88| 国产综合精品久久亚洲| 国产成人精品久久免费动漫| 日日躁夜夜躁狠狠久久AV| 久久只有这里有精品4| 久久一本综合| 久久精品无码专区免费| 四虎国产永久免费久久| 国产99久久精品一区二区| 伊人久久大香线蕉综合网站| 国产精品青草久久久久福利99| 国产精品久久国产精品99盘 | 久久精品成人一区二区三区| 成人久久综合网| 人人狠狠综合久久亚洲88| 久久99国产精品久久99果冻传媒| 国产∨亚洲V天堂无码久久久|