青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

QuXiao

每天進步一點點!

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  50 隨筆 :: 0 文章 :: 27 評論 :: 0 Trackbacks

#

題目來源:

PKU 1018 Communication System

 

算法分類:

枚舉+貪心

 

原文:

Communication System

Time Limit:1000MS  Memory Limit:10000K

Description

We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices. For each device, we are free to choose from several manufacturers. Same devices from two manufacturers differ in their maximum bandwidths and prices.
By overall bandwidth (B) we mean the minimum of the bandwidths of the chosen devices in the communication system and the total price (P) is the sum of the prices of all chosen devices. Our goal is to choose a manufacturer for each device to maximize B/P.

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by the input data for each test case. Each test case starts with a line containing a single integer n (1 ≤ n ≤ 100), the number of devices in the communication system, followed by n lines in the following format: the i-th line (1 ≤ i ≤ n) starts with mi (1 ≤ mi ≤ 100), the number of manufacturers for the i-th device, followed by mi pairs of positive integers in the same line, each indicating the bandwidth and the price of the device respectively, corresponding to a manufacturer.

Output

Your program should produce a single line for each test case containing a single number which is the maximum possible B/P for the test case. Round the numbers in the output to 3 digits after decimal point.

Sample Input

1 3

3 100 25 150 35 80 25

2 120 80 155 40

2 100 100 120 110

 

Sample Output

0.649

 

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest

 

 

中文描述:

你需要購買n種設備來組一個通信系統,每一種設備,又是由一些不同的制造商生產的,不同制造商生產的同種設備會有不同的帶寬和價格。現在你要在每一個設備的制造商中選一個,使得購買的n種設備,它們帶寬的最小值與價格之和的比最大。

 

題目分析:

一開始想到的就是暴搜,但是搜索的深度達到100,時間肯定是不允許的。想要解決這題,必須找到一個好的查找策略。再想想看這題的特點,最后的答案,帶寬是選取所有設備中的最小值,而價格是選取所有設備的價格總和。如果某個制造商生產的某種設備,它的帶寬較高而價格較低,那么選取它的可能性就比較大。再進一步說,如果所選取的n種設備的帶寬的最小值b已經確定,那么對于某種設備,我們就可以在那些生產這種設備的,帶寬大于等于b的制造商中進行選擇。當然是選那個價格最低的設備,因為答案的分子已經確定為b,所以分母越小越好。看來只要枚舉b,再對于每個設備貪心的選擇最小價格就可以了,時間復雜度為OmnB),B為帶寬枚舉的數量。但問題又來了,應該怎么枚舉帶寬,題目中并未給出帶寬的取值范圍,如果從0..maxB一個一個枚舉的話,既費時又會造成過多重復情況(如果枚舉那些在輸入中出現的兩個連續帶寬之間的值,最后的答案是一樣的)。所以我們應該采取某個方法記錄輸入中出現過的帶寬(STL中的set是個不錯的選擇),再枚舉這些帶寬。在枚舉中,可能出現這種情況:枚舉b,選擇了n種設備,但選擇的所有設備的帶寬都大于b,那么最終用b/price就不是這種情況的正確答案。其實不用擔心,因為正確答案一定大于b/price。假設上面這種情況的實際帶寬最小值是b’,那個當我們再去枚舉b’時,至少有一個設備的帶寬等于b’,這次得到的答案也就是上面那種情況的答案,所以最終還是能得到正確解。

 

代碼:

#include <iostream>

#include <map>

#include <set>

#include <climits>

using namespace std;

 

const int MAX = 105;

 

struct Info

{

                int band, price;

};

 

struct Device

{

                int manuNum;

                Info info[MAX];

                map<int, int> minPrice;                 //map[i] = j 表示帶寬>=i的最小價格是j

                int minBand, maxBand;

};

 

Device device[MAX];

int deviceNum;

set<int> band;                                                                  //輸入中出現過的band

set<int>::iterator start, end;

int maxBand, minBand;                                 //需要枚舉的band的最值

 

int cmp( const void *a , const void *b )

{

                Info *c = (Info *)a;

                Info *d = (Info *)b;

                if(c->band != d->band)

                                return d->band - c->band;

                else

                                return c->price - d->price;

}

 

void Input ()

{

                int i, j, max, min;

                band.clear();

                cin>>deviceNum;

                for (i=0; i<deviceNum; i++)

                {

                                device[i].minBand = INT_MAX;

                                device[i].maxBand = -1;

                                cin>>device[i].manuNum;

                                for (j=0; j<device[i].manuNum; j++)

                                {

                                                cin>>device[i].info[j].band>>device[i].info[j].price;

                                                band.insert(device[i].info[j].band);

                                                if ( device[i].info[j].band > device[i].maxBand )

                                                                device[i].maxBand = device[i].info[j].band;

                                                if ( device[i].info[j].band < device[i].minBand )

                                                                device[i].minBand = device[i].info[j].band;

                                }

                                                               

                }

}

 

void Pre ()                                           //預處理

{

                int i, j, min, b;

                //計算所需枚舉的帶寬的最值

                maxBand = INT_MAX;                   //maxBand為所有設備帶寬最大值的最小值

                minBand = INT_MAX;                    //minBand為所有設備帶寬最小值的最小值

                for (i=0; i<deviceNum; i++)

                {

                                if ( device[i].maxBand < maxBand )

                                                maxBand = device[i].maxBand;

                                if ( device[i].minBand < minBand )

                                                minBand = device[i].minBand;

                }

 

                //對于每個設備,找到帶寬大于等于某一值的最小價格

                for (i=0; i<deviceNum; i++)

                {

                                //band從大到小,band相等時price從小到大

                                qsort(device[i].info, device[i].manuNum, sizeof(Info), cmp);

                                device[i].minPrice.clear();

                                min = device[i].info[0].price;

                                b = device[i].info[0].band;

                                device[i].minPrice[b] = min;

                                for (j=1; j<device[i].manuNum; j++)

                                {

                                                if ( device[i].info[j].band == b )

                                                                continue;

                                                if ( device[i].info[j].price < min )

                                                {

                                                                min = device[i].info[j].price;

                                                }

                                                b = device[i].info[j].band;

                                                device[i].minPrice[b] = min;

                                }

                }             

}

 

void Solve ()

{

                Pre();

 

                int b, i, totalPrice;

                double rate, ans;

                map<int, int>::iterator it;

                ans = 0;

                start = band.find(minBand);

                end = band.find(maxBand);

                end ++;

                while ( start != end )

                {

                                b = *start;

                                start ++;

                                totalPrice = 0;

                                for (i=0; i<deviceNum; i++)

                                {

                                                //找到帶寬大于等于b的最小價格

                                                for (it=device[i].minPrice.begin(); it!=device[i].minPrice.end(); it++)

                                                {

                                                                if ( it->first >= b )

                                                                {

                                                                                totalPrice += it->second;

                                                                                break;

                                                                }

                                                }

 

                                }

                                rate = double(b) / totalPrice;

                                if ( rate > ans )

                                                ans = rate;

                }

 

                printf("%.3f\n", ans);

}

 

int main ()

{

                int test;

                cin>>test;

                while ( test -- )

                {

                                Input ();

                                Solve ();

                }

 

                return 0;

}

posted @ 2008-04-25 21:25 quxiao 閱讀(1552) | 評論 (6)編輯 收藏

     摘要: 解題報告   題目來源: PKU 3513 Let's Go to the Movies   分類: 樹形DP   原文: Let's Go to the Movies   Time Limit: 1000MS ...  閱讀全文
posted @ 2008-03-25 23:16 quxiao 閱讀(575) | 評論 (0)編輯 收藏

解題報告

 

題目來源:

PKU 1505 Copying Books

 

算法分類:

DP

 

原文:

Copying Books

Time Limit: 3000MS


Memory Limit: 10000K

Total Submissions: 1806


Accepted: 404

Description

Before the invention of book-printing, it was very hard to make a copy of a book. All the contents had to be re-written by hand by so called scribers. The scriber had been given a book and after several months he finished its copy. One of the most famous scribers lived in the 15th century and his name was Xaverius Endricus Remius Ontius Xendrianus (Xerox). Anyway, the work was very annoying and boring. And the only way to speed it up was to hire more scribers.

Once upon a time, there was a theater ensemble that wanted to play famous Antique Tragedies. The scripts of these plays were divided into many books and actors needed more copies of them, of course. So they hired many scribers to make copies of these books. Imagine you have m books (numbered 1, 2 ... m) that may have different number of pages (p1, p2 ... pm) and you want to make one copy of each of them. Your task is to divide these books among k scribes, k <= m. Each book can be assigned to a single scriber only, and every scriber must get a continuous sequence of books. That means, there exists an increasing succession of numbers 0 = b0 < b1 < b2, ... < bk-1 <= bk = m such that i-th scriber gets a sequence of books with numbers between bi-1+1 and bi. The time needed to make a copy of all the books is determined by the scriber who was assigned the most work. Therefore, our goal is to minimize the maximum number of pages assigned to a single scriber. Your task is to find the optimal assignment.

Input

The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case consists of exactly two lines. At the first line, there are two integers m and k, 1 <= k <= m <= 500. At the second line, there are integers p1, p2, ... pm separated by spaces. All these values are positive and less than 10000000.

Output

For each case, print exactly one line. The line must contain the input succession p1, p2, ... pm divided into exactly k parts such that the maximum sum of a single part should be as small as possible. Use the slash character ('/') to separate the parts. There must be exactly one space character between any two successive numbers and between the number and the slash.

If there is more than one solution, print the one that minimizes the work assigned to the first scriber, then to the second scriber etc. But each scriber must be assigned at least one book.

Sample Input

2

9 3

100 200 300 400 500 600 700 800 900

5 4

100 100 100 100 100

Sample Output

100 200 300 400 500 / 600 700 / 800 900

100 / 100 / 100 / 100 100

Source

Central Europe 1998

 

 

中文描述:

題目大意是給你m1…m)本書,每本書有Pm頁,用kk<=m)個員工來復印這些書。每本書只能分配給一個員工來復印,并且每個員工必須復印一段連續的書籍,每個員工復印的時間取決于所復印書籍的總頁數。讓你給出相應的分配,使得分配給員工的書籍頁數的最大值盡量小。注意,如果有多種分配的方案,使得第一個員工的書籍頁數盡量少,其次是第二個、第三個……以此類推。

 

題目分析:

我們可以從后往前推,最后一個員工,也就是第k個員工,他至少要復印第m本書,至多可以復印第k本到第m本(因為至少要分配給前k-1個員工每人一本書)。假設,第k名員工復制第ik<=i<=m)本書到第m本書,那么,所有員工復印書籍的最小時間就為第k名員工所需的時間以及前k-1名員工復制前i-1本書所需最小時間的較大的那個時間。這樣,問題的規模就從k個員工復印m本書減小到了k-1個員工復印i-1本書,而且求解過程中會不斷遇到前a個員工復印前b本書的最小時間。為了減小問題的規模以及記錄重復子問題的解,就可以用DP

但僅僅算出最小時間的不夠的,還要給出分配的方案,這個稍微有點繁瑣。因為題目中說,如果有多種最優的分配方案,應該讓前面的員工分配的頁數盡量少。那么,可以從后推,在當前的員工所復印的書籍頁數沒有超過最大頁數的情況下,讓其復印的頁數最大化。如果超過了最大頁數,就把這本書分配給前一名員工。最后再按順序將分配結果輸出出來。

 

代碼:

#include <cstdio>

#include <climits>

#include <cstring>

 

const int MAX = 505;

int book[MAX];

__int64 total[MAX];                        //1~n本書的頁數

int k, m;

__int64 f[MAX][MAX];                  //f[i][j] = k 表示前i個人復制前j本書所需最少時間是k

__int64 max;

void Input ()

{

                scanf("%d%d", &m, &k);

                int i;

                for (i=1; i<=m; i++)

                                scanf("%d", &book[i]);

}

 

__int64 Sum (int s, int e)                                               //s本書到第e本書的總頁數

{

                return (total[e] - total[s-1]);

}

 

__int64 Max (__int64 a, __int64 b)

{

                return ( a>b?a:b );

}

 

__int64 Min (int x, int y)                                //x個人復制前y本書所需的最少時間        x<=y

{

//考慮特殊情況

                if ( f[x][y] != -1 )

                                return f[x][y];

                if ( y == 0 )

                                return ( f[x][y] = 0 );

                if ( x == 0 )

                                return ( f[x][y] = INT_MAX );

 

                int i;

                __int64 temp;

                f[x][y] = INT_MAX;

                for (i=x-1; i<y; i++)

                {

//x個人復制第i+1到第y本書與前x-1個人復制前i本書的時間較大的時間

                                temp = Max( Min(x-1, i), Sum(i+1, y) );                 

                                if ( temp < f[x][y] )

                                {

                                                f[x][y] = temp;

                                }

                }

                return f[x][y];

}

 

void Output ()

{

                int i, p;

                __int64 temp;

                int slash[MAX];

                max = f[k][m];

                memset(slash, 0, sizeof(slash));

                temp = 0;

                p = k;

                for (i=m; i>0; i--)

                {

                                //讓后面的員工盡量復印最多的書籍

                                if ( temp + book[i] > max || i < p )

                                {

                                                slash[i] = 1;

                                                temp = book[i];

                                                p --;

                                }

                                else

                                {

                                                temp += book[i];

                                }

                }

 

                for (i=1; i<=m; i++)

                {

                                printf("%d", book[i]);

                                if ( slash[i] == 1 )

                                                printf(" / ");

                                else if ( i != m )

                                                printf(" ");

                }

                printf("\n");

}

 

void Solve ()

{

                int i, j;

                //預處理書籍頁數的和

                total[0] = 0;

                for (i=1; i<=m; i++)

                                total[i] = total[i-1] + book[i];

 

                memset(f, -1, sizeof(f));

               

                Min(k, m);

               

                Output();

}

 

int main ()

{

                int test;

                scanf("%d", &test);

                while ( test-- )

                {

                                Input ();

                                Solve ();

                }

 

                return 0;

}

 

 

程序分析與心得:

時間復雜度O(n2),空間復雜度O(n2)

在用記憶化搜索解決DP問題時,往往比較符合人的思維,容易想到模型,編程比較簡單。在解題過程中,除了可以按照常理順著推,也可以嘗試逆向思維,從最后的狀態倒著推,這樣可以使問題想得更加透徹,有比較好的效果。

posted @ 2008-03-10 15:11 quxiao 閱讀(568) | 評論 (0)編輯 收藏

題目大意:
    給你n個藥的序列,牛從時間1開始吃藥,在奇數時間吃藥可以增加彈跳力,在偶數時間吃藥則會減少彈跳力。在某一時間,你可以跳過一些藥,但一旦吃過某種藥,你就不能在選前面的藥了。問你某一個吃藥的序列,使牛最終的彈跳力最大。

思路:
    雖然題目不難,但思考題目的過程十分有意思。對于某種藥,共有4中狀態:在奇數時間吃、在奇數時間不吃、在偶數時間吃以及在偶數時間不吃。關鍵在于這4種狀態之間的轉移。因為如果跳過某種藥是不需要花費時間的,所以在某2次的吃藥時間內,時間相當于是靜止的,一直維持在第1次吃藥的時間段內。
    所以可用一數組max[i][2][2]表示狀態,第i種藥在奇/偶時間段內吃/不吃。可得狀態轉移可表示為:
    max[i][0][0] = Max (max[i-1][0][0], max[i-1][0][1]);
    max[i][0][1] = Max (max[i-1][1][0], max[i-1][1][1]) - high[i];
    max[i][1][0] = Max (max[i-1][1][0], max[i-1][1][1]);
    max[i][1][1] = Max (max[i-1][0][0], max[i-1][0][1]) + high[i];

代碼:

#include <iostream>
using namespace std;

const int MAX = 150005;
int high[MAX];
int max[MAX][2][2];
int n;

void Input ()
{
    scanf("%d", &n);
    int i;
    for (i=1; i<=n; i++)
        scanf("%d", &high[i]);

}

int Max (int a, int b)
{
    return ( a>b?a:b );
}

void Solve ()
{
    int i;
    for (i=1; i<=n; i++)
    {
        max[i][0][0] = Max (max[i-1][0][0], max[i-1][0][1]);
        max[i][0][1] = Max (max[i-1][1][0], max[i-1][1][1]) - high[i];
        max[i][1][0] = Max (max[i-1][1][0], max[i-1][1][1]);
        max[i][1][1] = Max (max[i-1][0][0], max[i-1][0][1]) + high[i];
    }
    printf("%d\n", Max ( Max(max[n][0][0], max[n][0][1]), Max(max[n][1][0], max[n][1][1])) );
}

int main ()
{
    Input ();
    Solve ();

    return 0;
}
posted @ 2008-02-02 21:41 quxiao 閱讀(954) | 評論 (0)編輯 收藏

題目大意:
    給定n個連續的長度為1的矩形的高度h(1<=n<=100000,0<=hi<=1000000000),問你其中能構成的最大矩形的面積是多少。

思路:
    很顯然,用DP。但關鍵是怎樣表示狀態,一開始想用一個二維數組min[][]表示從i~j的最小高度,面積就等于min[i][j]*(j-i+1)。但很不幸,根據題目給定的n的范圍,這個二維數組根本無法創建。:(
    后來從論壇上得到提示,因為對于圖中的某個面積最大的矩形,必然有一個最低的高度h[k],即矩形的高等于h[k],以第k塊矩形的高度,最左邊可以到達這個矩形的左邊,最右邊可以到達這個矩形的右邊。所以,可以以每塊矩形進行擴展,求出最左邊和最右邊(即兩邊的高度都大于等于這塊的高度),得出面積s[i],這樣就可求出最大的s[i]了。

代碼:

#include <cstdio>

const int MAX = 100005;
__int64 h[MAX];
__int64 left[MAX], right[MAX];        //left[i] = j表示第i個矩形以它的高度到達最左邊的下標
int n;

bool Input ()
{
    scanf("%d", &n);
    if ( n == 0 )
        return false;
    int i;
    for (i=1; i<=n; i++)
        scanf("%I64d", &h[i]);
    h[0] = h[n+1] = -1;
    return true;
}

void Solve ()
{
    int i;
    __int64 temp, max;
    for (i=1; i<=n; i++)
    {
        left[i] = right[i] = i;
    }

    for (i=1; i<=n; i++)
    {
        while ( h[left[i]-1] >= h[i] )
            left[i] = left[left[i]-1];
    }
    for (i=n; i>0; i--)
    {
        while ( h[right[i]+1] >= h[i] )
            right[i] = right[right[i]+1];
    }

    max = 0;
    for (i=1; i<=n; i++)
    {
        temp = h[i] * (right[i] - left[i] + 1);
        if ( temp > max )
            max = temp;
    }

    printf("%I64d\n", max);
}

int main ()
{
    while ( Input() )
    {
        Solve();
    }

    return 0;
}


posted @ 2008-02-01 19:34 quxiao 閱讀(1857) | 評論 (0)編輯 收藏

題目大意:

    給定一個時間期間n,電腦的價格c,以及電腦的維修費用m(y,z)(第y臺電腦從y年用到第z年總的維修費用)。讓你求出在期限n中使用電腦的最低費用。

思路:
    為了讓總費用最低,你必須作出這樣的決策:假設你正在使用某一臺電腦已用到y年,你y+1年是繼續用這臺電腦,還是重新買第y+1臺電腦(注意,這里的y+1是指輸入中的第y+1行電腦,而不是指你已購買了y+1臺電腦,因為y年只能買輸入中的第y行電腦,為了不產生混淆,將電腦用編號表示)。顯然,某一階段的最優解并不能一定導致全局的最優解,所以肯定不能用貪心。
    我們從最后的情況來考慮,最后必然是某一個編號為y的電腦,從第y年使用到第n年,而前面的1~y-1年,自己只可能購買編號為1~y-1的電腦使用到y-1年。這樣,問題的范圍就減小了,從編號為1~n的電腦使用n年,降低到了編號為1~y-1的電腦使用y-1年。經分析,可推出遞推式:
    F[n] = min { F[i] + c + m[i+1][n] | 0<=i<=n-1 }
F[n]表示n臺電腦使用n年的最低費用

代碼:

#include <cstdio>
#include <climits>
#include <cstring>

const int MAX = 1005;
int n, c;
int mend[MAX][MAX];
int f[MAX];
int cost;

bool Input ()
{
    if ( scanf("%d", &c) == EOF )
        return false;
    scanf("%d", &n);
    int i, j;
    for (i=1; i<=n; i++)
    {
        for (j=i; j<=n; j++)
            scanf("%d", &mend[i][j]);
    }
    return true;
}


void Solve ()
{
    int i, j;
    memset(f, 0, sizeof(f));
    for (i=1; i<=n; i++)
    {
        f[i] = INT_MAX;
        for (j=0; j<i; j++)
        {
            if ( f[j] + mend[j+1][i] + c < f[i] )
                f[i] = f[j] + mend[j+1][i] + c;
        }
    }
    printf("%d\n", f[n]);
}

int main ()
{
    while ( Input() )
    {
        Solve ();
    }

    return 0;
}
posted @ 2008-01-28 14:45 quxiao 閱讀(483) | 評論 (0)編輯 收藏

題意:
    就是有這樣一個序列:1 12 123 1234 12345 .....,輸入序列的下標,讓你算出該序列所在下標的字符

思路:
    一開始想用字符串模擬來做,結果TLE。后來看了discuss,又想了一下,發現可以按規律將序列分成幾段,然后再在每段中查找。具體做法是:先按序列 中數字的位數來分,112123...123456789是一段,1..10 1..11 1..12 ... 1..99是一段,1..100 ... 1..999是一段,以此類推。確定了是在上面的哪一段以后,再按類似的思想確定這個下標是在哪個12345...n的序列,最后判斷是在其中哪個數字的 哪一位。

代碼:
#include <iostream>
#include <cmath>
using namespace std;

const long long a[] = {0, 45, 9045, 1395495, 189414495, 2147483648};            //112123...9, 11231234...99, ... 的位數
const long long b[] = {1, 11, 192, 2893, 38894, 488895, 5888896};                //1, 1234...10, 1234...100, ...的位數

int digit (int n)
{
    int ans = 1;
    while ( n / 10 != 0 )
    {
          n /= 10;
          ans ++;
    }
    return ans;
}

char Pos (int n, long long index)      //在1234...n中找到下標為index的字符
{
     long long i, j;
     long long pos = 0;
     for (i=1; i<=n; i++)
     {
         pos += digit(i);
         if ( pos >= index )
            break;
     }
    
     pos -= digit(i);               //定位在i上
     j = digit(i) - (index - pos);
     //if ( j == digit(i) - 1 )
     //   cout<<endl;
     while ( j > 0 )
     {
           i /= 10;
           j --;
     }

     return (i % 10) + '0';
}


char Find (long long pos)
{
     long long p, t;
     int index = 0;
     int temp;
     while ( a[index] < pos )
     {
           index ++;
     }
     p = a[index - 1];
    
     p += b[index - 1];
     temp = int(pow(10.0, index-1));
     t = b[index - 1] + index;
     while ( p < pos )
     {
           p += t;
           t += index;
           temp ++;
     }
    
     p -= t - index;
    
     return Pos(temp, pos-p);
}

int main ()
{
    int test;
    long long i;
    cin>>test
    while ( test-- )
    {
          cin>>i;
          cout<<Find(i)<<endl;
    }

    return 0;
posted @ 2008-01-19 16:46 quxiao 閱讀(1717) | 評論 (0)編輯 收藏

    一開始看還以為是一道博弈的題目,再仔細看才發現并不是博弈,也不是很難。大致意思是:有n堆石子,第i堆有Ki個石子,每輪一方可以從任意堆中取出一個或多個石子,所有石子都被取光時,游戲也結束了,那個最后一輪拿走石子的人就是勝利者。問你有多少種方法使對方處于必敗的局面。題目并不難,是因為題目中已經告訴你了產生必敗局面的條件:如果所有堆的石子數的異或和為0,那么處于此局面的人就必敗。
    因為每次只能從一個堆中取石子,所以只要對于每個堆i,先求出其他所有堆的異或和temp,再看0~Ki-1與這個異或和再進行異或是否為0,只要為0就得到一種勝利的方法。自己先是想枚舉0~Ki-1,與temp進行異或。后來感覺沒有必要,只要Ki>temp就可以了,因為若從堆i中取出x個石子,Ki-x異或temp==0 <==> Ki-x==temp,只要Ki>temp,就存在Ki-x==temp。

#include <cstdio>

#define PILE 1001

__int64 stone[PILE], test;       //test為所有石子數的異或和
int piles;

bool Input ()
{
    scanf("%d", &piles);
    if ( piles == 0 )
        return false;
   
    int i;
    for (i=0; i<piles; i++)
        scanf("%I64d", &stone[i]);
    return true;
}

void Solve ()
{
    int i, ans;
    __int64 temp;
    test = 0;
    ans = 0;
    for (i=0; i<piles; i++)
        test ^= stone[i];
   
    if ( test != 0 )
    {
        for (i=0; i<piles; i++)
        {
            temp = test ^ stone[i];      //再與stone[i]做一次異或,相當于除stone[i]對其他所有堆的石子進行異或

            if ( stone[i] > temp )
                ans++;
        }
    }
    printf("%d\n", ans);
}

int main ()
{
    while ( Input() )
    {
        Solve();
    }
   
    return 0;
}


posted @ 2007-12-07 21:41 quxiao 閱讀(734) | 評論 (4)編輯 收藏

    地圖上有一些beeper,讓你從起點搜集所有beeper,再回到起點。但你只可以水平或者豎直的走,不能走對角線。讓你找出這樣走的最短路徑長度。
    因為地圖最大只有20×20,而beeper最多也只有10個,所以可以考慮用深搜,找到所有可能路徑,在其中加一些簡單的減枝就可以了。起初以為會超時,可最后還是0ms。:)

Source Code

Problem: 2907
User: QuXiao
Memory: 176K
Time: 0MS
Language: C++
Result: Accepted
  • Source Code
  • #include <iostream>
    #include <climits>
    using namespace std;

    struct Point
    {
    int x, y;
    };

    int num, X, Y;
    Point start, beeper[15];
    int shortest;
    int visited[15];


    int Length (Point p1, Point p2)
    {
    return abs(p1.x - p2.x) + abs(p1.y - p2.y);
    }

    void Input ()
    {
    int i;
    cin>>X>>Y;
    cin>>start.x>>start.y;
    cin>>num;
    for (i=0; i<num; i++)
    cin>>beeper[i].x>>beeper[i].y;
    }

    void DFS (int cur, int len, int n)
    {
    if ( n == num )
    {
    int t = Length(beeper[cur], start);
    if ( len + t < shortest )
    shortest = len + t;
    }
    else if ( len < shortest )
    {
    int i;
    for (i=0; i<num; i++)
    {
    if ( visited[i] == 0 )
    {
    visited[i] = 1;
    DFS (i, len+Length(beeper[cur], beeper[i]), n+1);
    visited[i] = 0;
    }
    }
    }
    }


    void Solve ()
    {
    int i, t;
    shortest = INT_MAX;
    memset(visited, 0, sizeof(visited));
    for (i=0; i<num; i++)
    {
    t = Length(beeper[i], start);
    visited[i] = 1;
    DFS (i, t, 1);
    visited[i] = 0;
    }
    cout<<"The shortest path has length "<<shortest<<endl;
    }

    int main ()
    {
    int test;
    cin>>test;
    while ( test-- )
    {
    Input ();
    Solve ();
    }

    return 0;
    }



posted @ 2007-12-07 19:31 quxiao 閱讀(382) | 評論 (1)編輯 收藏

    大家好,我對算法比較感興趣。希望能借此平臺,與我有同樣愛好的朋友們能夠多多交流,共同進步!
posted @ 2007-12-07 19:11 quxiao 閱讀(70) | 評論 (0)編輯 收藏

僅列出標題
共5頁: 1 2 3 4 5 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久久噜噜噜久久狠狠50岁| 亚洲精品国产精品国自产观看| 欧美日韩亚洲一区二区三区| 黄色亚洲网站| 亚洲影音先锋| 亚洲国产精品第一区二区三区| 亚洲乱码国产乱码精品精98午夜 | 亚洲国产日韩欧美一区二区三区| 欧美影院在线播放| 亚洲精品视频一区| 久久影音先锋| 国一区二区在线观看| 欧美在线视频免费播放| 正在播放欧美视频| 欧美日韩国产在线观看| 亚洲深夜激情| 亚洲国产精品va| 欧美大片在线观看一区二区| 亚洲激情成人| 亚洲欧洲一区二区在线观看| 欧美激情综合在线| 99视频精品全国免费| 日韩视频一区二区| 国产精品jvid在线观看蜜臀| 亚洲欧美在线免费| 亚洲欧美一区在线| 国产一区二区三区成人欧美日韩在线观看 | 午夜国产精品影院在线观看| 国产精品一二三四区| 欧美在线免费看| 久久av二区| 亚洲第一网站| 亚洲精品美女在线| 国产精品私拍pans大尺度在线| 久久狠狠亚洲综合| 久久露脸国产精品| 99国内精品| 亚洲欧美春色| 亚洲国产91| 一区二区日韩精品| 国产小视频国产精品| 欧美成人免费一级人片100| 老司机67194精品线观看| 一区二区成人精品| 久久不见久久见免费视频1| 亚洲激情婷婷| 亚洲一级一区| 在线日韩欧美视频| 9i看片成人免费高清| 韩国av一区| 99国内精品久久| 一区二区三区在线免费视频| av成人老司机| 亚洲国产精品www| 亚洲自拍都市欧美小说| 亚洲国产91精品在线观看| 亚洲午夜在线视频| 亚洲人成啪啪网站| 欧美一级免费视频| 一区二区三区视频在线观看| 久久精品视频在线免费观看| 国产精品99久久久久久久女警| 久久九九热re6这里有精品| 亚洲网址在线| 欧美国产先锋| 欧美成人按摩| 国产一区二区三区四区hd| av成人激情| 亚洲免费观看| 老鸭窝亚洲一区二区三区| 欧美一区二区三区视频| 欧美日韩在线免费视频| 亚洲成色最大综合在线| 韩日午夜在线资源一区二区| 亚洲专区免费| 午夜精品久久久久久久99热浪潮 | 欧美日韩综合另类| 欧美高清在线一区| 国产一区久久久| 香蕉久久夜色精品| 亚洲在线一区二区三区| 欧美人在线观看| 老牛国产精品一区的观看方式| 国产精品视频成人| 亚洲无线观看| 亚洲欧美日韩精品久久亚洲区| 欧美精品在欧美一区二区少妇| 欧美激情一区三区| 亚洲国产女人aaa毛片在线| 久久久久看片| 欧美大片网址| 亚洲精品1区| 欧美激情精品久久久久久蜜臀| 免费亚洲一区二区| 亚洲国产岛国毛片在线| 久久一区精品| 欧美国产日本在线| 激情欧美丁香| 免费人成精品欧美精品| 亚洲二区视频| 亚洲作爱视频| 国产精品久在线观看| 亚洲一区二区av电影| 欧美一区视频| 在线观看国产成人av片| 美女脱光内衣内裤视频久久影院| 欧美顶级大胆免费视频| 日韩一区二区久久| 国产精品久久久爽爽爽麻豆色哟哟| 亚洲天堂男人| 久久久午夜精品| 亚洲黄色免费网站| 欧美久久精品午夜青青大伊人| 亚洲精品小视频| 欧美在线播放| 亚洲国产精品久久精品怡红院| 欧美黄色视屏| 亚洲夜晚福利在线观看| 久久免费的精品国产v∧| 亚洲欧洲在线一区| 欧美日韩综合视频| 久久狠狠婷婷| 91久久一区二区| 性亚洲最疯狂xxxx高清| 亚洲夫妻自拍| 国产精品hd| 免费高清在线视频一区·| 在线亚洲一区| 欧美成人在线影院| 亚洲欧美一区二区原创| 国产在线成人| 欧美日韩色一区| 亚洲欧美日韩一区二区在线 | 精品动漫3d一区二区三区免费| 麻豆精品一区二区av白丝在线| 99精品欧美一区| 美女黄网久久| 欧美亚洲综合久久| 一本色道久久综合亚洲精品小说 | 欧美色一级片| 久久久www| 中国亚洲黄色| 亚洲高清一区二| 久久久精品性| 亚洲欧美日韩视频一区| 亚洲人成网在线播放| 国内久久婷婷综合| 国产精品mm| 欧美欧美天天天天操| 久久婷婷丁香| 欧美主播一区二区三区美女 久久精品人 | 亚洲激情中文1区| 国产日韩欧美一区在线| 欧美日韩精品二区第二页| 久久婷婷丁香| 久久久国产视频91| 午夜精品www| 亚洲一区二区成人| 一区二区精品国产| 亚洲看片网站| 亚洲激情图片小说视频| 欧美a级片网站| 久久影院午夜片一区| 欧美在线三级| 欧美一区二区三区男人的天堂| 亚洲一区二区黄色| 一本色道久久88综合亚洲精品ⅰ | 久久激情综合| 午夜精品亚洲一区二区三区嫩草| 一本一本久久a久久精品牛牛影视| 亚洲成色777777在线观看影院| 国产午夜精品一区理论片飘花 | 久久日韩粉嫩一区二区三区| 欧美影院精品一区| 久久国产精品久久久久久| 午夜欧美不卡精品aaaaa| 亚洲综合色网站| 亚洲欧美一区二区在线观看| 亚洲一区尤物| 亚洲欧美综合精品久久成人| 亚洲欧美中日韩| 欧美在线视频免费| 久久青草久久| 欧美激情视频在线播放| 亚洲福利av| 亚洲久色影视| 亚洲一区中文字幕在线观看| 亚洲一区二区动漫| 性欧美xxxx视频在线观看| 欧美专区亚洲专区| 久久久久久久综合狠狠综合| 麻豆精品传媒视频| 欧美日韩免费区域视频在线观看| 欧美日韩视频在线一区二区| 国产精品扒开腿做爽爽爽软件| 国产精品乱码人人做人人爱| 国产色爱av资源综合区| 尤物精品国产第一福利三区 | 日韩天堂在线观看| 亚洲视频一区二区|