??xml version="1.0" encoding="utf-8" standalone="yes"?>91超碰碰碰碰久久久久久综合,国内精品久久久久影院一蜜桃,久久国产高清字幕中文http://m.shnenglu.com/ACM-Boy/category/5700.htmlzh-cnSat, 16 Aug 2008 13:31:49 GMTSat, 16 Aug 2008 13:31:49 GMT60PKU 1733 Parity gamehttp://m.shnenglu.com/ACM-Boy/archive/2008/08/15/58919.htmlACM-BoyACM-BoyFri, 15 Aug 2008 03:23:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/08/15/58919.htmlhttp://m.shnenglu.com/ACM-Boy/comments/58919.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/08/15/58919.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/58919.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/58919.html
思\Q?br>    告诉你[a,b]之间1个数的奇偶情况,那么你就可以在a-1和b之间q一条边Q权值就是其奇偶情况。这样一来,比如[1,2]和[3,4]的情况已知,[1,4]的情况也q道了。当题目l出[a,b]的情冉|Q首先分别从a和b往上找Q找C们的根r1和r2Q如果r1 !=  r2Q表Ca,b之间的奇偶情况还不确定,将r1和r2之间qv来,Ҏa到r1的权倹{b到r2的权值和题目所l的奇偶情况Q设|r1和r2之间的权|以符合题目要求。若r1 == r2Q则表示[a,b]之间情况已确定,Ҏa到r1的权值和b到r2的权|可以判断题目所l的[a,b]的情冉|否ؓ真?br>    其实当时做的时候,q不是很懂,但没惛_E里糊涂的AC了。推荐一下这个网:http://hi.baidu.com/fandywang_jlu/blog/item/b49e40893ddbb0b00f244485.htmlQ这里面介绍q查集挺详细的,q有不少推荐题目Q有些还不会做。:P

代码Q?br>
#include <iostream>
#include <map>
using namespace std;

const int MAX = 10005;

int n, p;
int pre[MAX];
int parity[MAX];        //i到目前集合的根的奇偶情况
map<int, int> numIndex;        //用于L?br>
int Find (int x)
{
    if ( pre[x] == -1 )
        return x;
    int f;
    f = Find(pre[x]);
    parity[x] = (parity[x] + parity[pre[x]]) % 2;    //此时pre[x]已指向最l的集合的根
    pre[x] = f;
    return f;
}

bool Query (int x, int y, int odd)
{
    int r1, r2;
    r1 = Find(x);
    r2 = Find(y);
    if ( r1 == r2 )
    {
        if ( (parity[x] + parity[y]) % 2 == odd )
            return true;
        else
            return false;
    }
    else            //只是r1接到r2下面Q这边还可以优化
    {
        pre[r1] = r2;
        parity[r1] = (parity[x] + parity[y] + odd) % 2;
        return true;
    }
}

void Solve ()
{
    int i, x, y, index, idx1, idx2, odd;
    char s[10];
    scanf("%d%d", &n, &p);
    index = 0;
    for (i=0; i<p; i++)
    {
        scanf("%d%d%s", &x, &y, &s);
        x --;
        if ( numIndex.find(x) == numIndex.end() )
            numIndex[x] = index ++;
        idx1 = numIndex[x];
        if ( numIndex.find(y) == numIndex.end() )
            numIndex[y] = index ++;
        idx2 = numIndex[y];
        if ( strcmp(s, "odd") == 0 )
            odd = 1;
        else
            odd = 0;
        if ( Query(idx1, idx2, odd) == false )
        {
            break;
        }
    }
   
    printf("%d\n", i);
}

void Init ()
{
    memset(pre, -1, sizeof(pre));
}

int main ()
{
    Init();
    Solve();

    return 0;
}


ACM-Boy 2008-08-15 11:23 发表评论
]]>
PKU 1639 Picnic Planninghttp://m.shnenglu.com/ACM-Boy/archive/2008/07/30/57547.htmlACM-BoyACM-BoyWed, 30 Jul 2008 11:10:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/07/30/57547.htmlhttp://m.shnenglu.com/ACM-Boy/comments/57547.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/07/30/57547.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/57547.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/57547.html阅读全文

ACM-Boy 2008-07-30 19:10 发表评论
]]>
PKU 1037 A decorative fencehttp://m.shnenglu.com/ACM-Boy/archive/2008/05/20/50507.htmlACM-BoyACM-BoyTue, 20 May 2008 04:45:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/05/20/50507.htmlhttp://m.shnenglu.com/ACM-Boy/comments/50507.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/05/20/50507.html#Feedback2http://m.shnenglu.com/ACM-Boy/comments/commentRss/50507.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/50507.html阅读全文

ACM-Boy 2008-05-20 12:45 发表评论
]]>
PKU 2201 Cartesian Treehttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48158.htmlACM-BoyACM-BoyFri, 25 Apr 2008 13:27:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48158.htmlhttp://m.shnenglu.com/ACM-Boy/comments/48158.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48158.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/48158.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/48158.html阅读全文

ACM-Boy 2008-04-25 21:27 发表评论
]]>
PKU 1018 Communication Systemhttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48157.htmlACM-BoyACM-BoyFri, 25 Apr 2008 13:25:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48157.htmlhttp://m.shnenglu.com/ACM-Boy/comments/48157.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/04/25/48157.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/48157.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/48157.html 题目来源Q?/span>

PKU 1018 Communication System

 

法分类Q?/span>

枚D+贪心

 

原文Q?/span>

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

 

 

中文描述Q?/span>

你需要购?/span>nU设备来l一个通信pȝQ每一U设备,又是׃些不同的刉商生的,不同刉商生的同U设备会有不同的带宽和h根{现在你要在每一个设备的刉商中选一个,使得购买?/span>nU设备,它们带宽的最gh之和的比最大?/span>

 

题目分析Q?/span>

一开始想到的是暴搜Q但是搜索的深度辑ֈ100Q时间肯定是不允许的。想要解册题,必须扑ֈ一个好的查扄略。再x看这题的特点Q最后的{案Q带宽是选取所有设备中的最|而h格是选取所有设备的hd。如果某个制造商生的某U设备,它的带宽较高而hD低,那么选取它的可能性就比较大。再q一步说Q如果所选取?/span>nU设备的带宽的最?/span>b已经定Q那么对于某U设备,我们可以在那些生q种讑֤的,带宽大于{于b的制造商中进行选择。当然是选那个h格最低的讑֤Q因为答案的分子已经定?/span>bQ所以分母越越好。看来只要枚?/span>bQ再对于每个讑֤贪心的选择最h格就可以了,旉复杂度ؓOQ?/span>mnBQ,B为带宽枚丄数量。但问题又来了,应该怎么枚D带宽Q题目中q未l出带宽的取D_如果?/span>0..maxB一个一个枚丄话,既费时又会造成q多重复情况Q如果枚N些在输入中出现的两个q箋带宽之间的|最后的{案是一LQ。所以我们应该采取某个方法记录输入中出现q的带宽Q?/span>STL中的set是个不错的选择Q,再枚举这些带宽。在枚D中,可能出现q种情况Q枚?/span>bQ选择?/span>nU设备,但选择的所有设备的带宽都大?/span>bQ那么最l用b/price׃是这U情늚正确{案。其实不用担心,因ؓ正确{案一定大?/span>b/price。假设上面这U情늚实际带宽最值是b’Q那个当我们再去枚Db’Ӟ臛_有一个设备的带宽{于b’Q这ơ得到的{案也就是上面U情늚{案Q所以最l还是能得到正确解?/span>

 

代码Q?/span>

#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的最h格是j

                int minBand, maxBand;

};

 

Device device[MAX];

int deviceNum;

set<int> band;                                                                  //输入中出现过?/span>band

set<int>::iterator start, end;

int maxBand, minBand;                                 //需要枚丄band的最?/span>

 

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 ()                                           //预处?/span>

{

                int i, j, min, b;

                //计算所需枚D的带宽的最?/span>

                maxBand = INT_MAX;                   //maxBand为所有设备带宽最大值的最?/span>

                minBand = INT_MAX;                    //minBand为所有设备带宽最值的最?/span>

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

                {

                                if ( device[i].maxBand < maxBand )

                                                maxBand = device[i].maxBand;

                                if ( device[i].minBand < minBand )

                                                minBand = device[i].minBand;

                }

 

                //对于每个讑֤Q找到带宽大于等于某一值的最h?/span>

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

                {

                                //band从大到小Q?/span>band相等?/span>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的最h?/span>

                                                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;

}



ACM-Boy 2008-04-25 21:25 发表评论
]]>
PKU 3513 Let's Go to the Movieshttp://m.shnenglu.com/ACM-Boy/archive/2008/03/25/45395.htmlACM-BoyACM-BoyTue, 25 Mar 2008 15:16:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/03/25/45395.htmlhttp://m.shnenglu.com/ACM-Boy/comments/45395.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/03/25/45395.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/45395.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/45395.html阅读全文

ACM-Boy 2008-03-25 23:16 发表评论
]]>
pku 1505 Copying Bookshttp://m.shnenglu.com/ACM-Boy/archive/2008/03/10/44085.htmlACM-BoyACM-BoyMon, 10 Mar 2008 07:11:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/03/10/44085.htmlhttp://m.shnenglu.com/ACM-Boy/comments/44085.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/03/10/44085.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/44085.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/44085.html解题报告

 

题目来源Q?/span>

PKU 1505 Copying Books

 

法分类Q?/span>

DP

 

原文Q?/span>

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

 

 

中文描述Q?/span>

题目大意是给?/span>mQ?/span>1…mQ本书,每本书有Pm,?/span>kQ?/span>k<=mQ个员工来复印这些书。每本书只能分配l一个员工来复印Qƈ且每个员工必dCD连l的书籍Q每个员工复印的旉取决于所复印书籍的总页数。让你给出相应的分配Q得分配给员工的书c页数的最大值尽量小。注意,如果有多U分配的ҎQ得第一个员工的书籍|量,其次是第二个、第三个……以此cL?/span>

 

题目分析Q?/span>

我们可以从后往前推Q最后一个员工,也就是第k个员工,他至要复印W?/span>m本书Q至多可以复印第k本到W?/span>m本(因ؓ臛_要分配给?/span>k-1个员工每Z本书Q。假设,W?/span>k名员工复制第iQ?/span>k<=i<=mQ本书到W?/span>m本书Q那么,所有员工复Cc的最时间就为第k名员工所需的时间以及前k-1名员工复制前i-1本书所需最时间的较大的那个时间。这P问题的规模就?/span>k个员工复?/span>m本书减小Ck-1个员工复?/span>i-1本书Q而且求解q程中会不断遇到?/span>a个员工复印前b本书的最时间。ؓ了减问题的规模以及记录重复子问题的解,可以用DP?/span>

但仅仅算出最时间的不够的,q要l出分配的方案,q个E微有点J琐。因为题目中_如果有多U最优的分配ҎQ应该让前面的员工分配的|量。那么,可以从后推,在当前的员工所复印的书c页数没有超q最大页数的情况下,让其复印的页数最大化。如果超q了最大页敎ͼ把q本书分配给前一名员工。最后再按顺序将分配l果输出出来?/span>

 

代码Q?/span>

#include <cstdio>

#include <climits>

#include <cstring>

 

const int MAX = 505;

int book[MAX];

__int64 total[MAX];                        //1~n本书的页?/span>

int k, m;

__int64 f[MAX][MAX];                  //f[i][j] = k 表示?/span>i个h复制?/span>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)                                               //W?/span>s本书到第e本书的总页?/span>

{

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

}

 

__int64 Max (__int64 a, __int64 b)

{

                return ( a>b?a:b );

}

 

__int64 Min (int x, int y)                                //?/span>x个h复制?/span>y本书所需的最时?/span>        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++)

                {

//W?/span>x个h复制W?/span>i+1到第y本书与前x-1个h复制?/span>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;

                //预处理书c页数的?/span>

                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;

}

 

 

E序分析与心得:

旉复杂?/span>O(n2)Q空间复杂度O(n2)?/span>

在用记忆化搜索解?/span>DP问题Ӟ往往比较W合人的思维Q容易想到模型,~程比较单。在解题q程中,除了可以按照常理着推,也可以尝试逆向思维Q从最后的状态倒着推,q样可以佉K题想得更加透彻Q有比较好的效果?/span>



ACM-Boy 2008-03-10 15:11 发表评论
]]>
PKU 2181 Jumping Cowshttp://m.shnenglu.com/ACM-Boy/archive/2008/02/02/42409.htmlACM-BoyACM-BoySat, 02 Feb 2008 13:41:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/02/02/42409.htmlhttp://m.shnenglu.com/ACM-Boy/comments/42409.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/02/02/42409.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/42409.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/42409.html    l你n个药的序列,牛从旉1开始吃药,在奇数时间吃药可以增加弹跛_Q在偶数旉吃药则会减少弹蟩力。在某一旉Q你可以跌一些药Q但一旦吃q某U药Q你׃能在选前面的药了。问你某一个吃药的序列Q牛最l的弹蟩力最大?br>
思\Q?br>    虽然题目不难Q但思考题目的q程十分有意思。对于某U药Q共?中状态:在奇数时间吃、在奇数旉不吃、在偶数旉吃以及在偶数旉不吃。关键在于这4U状态之间的转移。因为如果蟩q某U药是不需要花Ҏ间的Q所以在?ơ的吃药旉内,旉相当于是静止的,一直维持在W?ơ吃药的旉D内?br>    所以可用一数组max[i][2][2]表示状态,WiU药在奇/偶时间段内吃/不吃。可得状态{Ud表示为:
    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];

代码Q?br>
#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;
}


ACM-Boy 2008-02-02 21:41 发表评论
]]>
PKU 2559 Largest Rectangle in a Histogramhttp://m.shnenglu.com/ACM-Boy/archive/2008/02/01/42366.htmlACM-BoyACM-BoyFri, 01 Feb 2008 11:34:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/02/01/42366.htmlhttp://m.shnenglu.com/ACM-Boy/comments/42366.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/02/01/42366.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/42366.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/42366.html题目大意Q?/span>
    l定n个连l的长度?的矩形的高度hQ?<=n<=100000Q?<=hi<=1000000000Q,问你其中能构成的最大矩形的面积是多?/span>

思\Q?/span>
    很显Ӟ用DP。但关键是怎样表示状态,一开始想用一个二l数lmin[][]表示从i~j的最高度,面积q于min[i][j]*(j-i+1)。但很不q,Ҏ题目l定的n的范_q个二维数组Ҏ无法创徏?(
    后来从论坛上得到提示Q因为对于图中的某个面积最大的矩ŞQ必然有一个最低的高度h[k]Q即矩Ş的高{于h[k]Q以Wk块矩形的高度Q最左边可以到达q个矩Ş的左边,最双可以到达q个矩Ş的右辏V所以,可以以每块矩形进行扩展,求出最左边和最双Q即两边的高度都大于{于q块的高度)Q得出面Us[i]Q这样就可求出最大的s[i]了?/span>

代码Q?/span>

#include <cstdio>

const int MAX = 100005;
__int64 h[MAX];
__int64 left[MAX], right[MAX];        //left[i] = j表示Wi个矩形以它的高度到达最左边的下?/span>
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;
}




ACM-Boy 2008-02-01 19:34 发表评论
]]>
pku 3486 Computershttp://m.shnenglu.com/ACM-Boy/archive/2008/01/28/42029.htmlACM-BoyACM-BoyMon, 28 Jan 2008 06:45:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/01/28/42029.htmlhttp://m.shnenglu.com/ACM-Boy/comments/42029.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/01/28/42029.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/42029.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/42029.html题目大意Q?/p>     l定一个时间期间nQ电脑的hcQ以及电脑的l修费用m(y,z)Q第y台电脑从yq用到第zqȝl修费用Q。让你求出在期限n中用电脑的最低费用?br>
思\Q?br>    Z让总费用最低,你必ML决策Q假设你正在使用某一台电脑已用到yq_你y+1q是l箋用这台电脑,q是重新买第y+1台电脑(注意Q这里的y+1是指输入中的Wy+1行电脑,而不是指你已购买了y+1台电脑,因ؓyq只能买输入中的Wy行电脑,Z不生؜淆,电脑用~号表示Q。显Ӟ某一阶段的最优解q不能一定导致全局的最优解Q所以肯定不能用贪心?br>    我们从最后的情况来考虑Q最后必然是某一个编号ؓy的电脑,从第yq用到Wnq_而前面的1~y-1q_自己只可能购买编号ؓ1~y-1的电脑用到y-1q。这P问题的范围就减小了,从编号ؓ1~n的电脑用nq_降低C~号?~y-1的电脑用y-1q。经分析Q可推出递推式:
    F[n] = min { F[i] + c + m[i+1][n] | 0<=i<=n-1 }
F[n]表示n台电脑用nq的最低费?br>
代码Q?br>
#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;
}


ACM-Boy 2008-01-28 14:45 发表评论
]]>
PKU 1019 Number Sequencehttp://m.shnenglu.com/ACM-Boy/archive/2008/01/19/41474.htmlACM-BoyACM-BoySat, 19 Jan 2008 08:46:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2008/01/19/41474.htmlhttp://m.shnenglu.com/ACM-Boy/comments/41474.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2008/01/19/41474.html#Feedback0http://m.shnenglu.com/ACM-Boy/comments/commentRss/41474.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/41474.html题意Q?br>     是有这样一个序列:1 12 123 1234 12345 .....Q输入序列的下标Q让你算序列所在下标的字符

思\Q?br>     一开始想用字W串模拟来做Q结果TLE。后来看了discussQ又想了一下,发现可以按规律将序列分成几段Q然后再在每D中查找。具体做法是Q先按序? 中数字的位数来分Q?12123...123456789是一D,1..10 1..11 1..12 ... 1..99是一D,1..100 ... 1..999是一D,以此cL。确定了是在上面的哪一D以后,再按cM的思想定q个下标是在哪个12345...n的序列,最后判断是在其中哪个数字的 哪一位?br>
代码Q?br> #include <iostream>
#include <cmath>
using namespace std;

const long long a[] = {0, 45, 9045, 1395495, 189414495, 2147483648};            //112123...9, 11231234...99, ... 的位?br> const long long b[] = {1, 11, 192, 2893, 38894, 488895, 5888896};                //1, 1234...10, 1234...100, ...的位?br>
int digit (int n)
{
    int ans = 1;
    while ( n / 10 != 0 )
    {
          n /= 10;
          ans ++;
    }
    return ans;
}

char Pos (int n, long long index)      //?234...n中找C标ؓindex的字W?br> {
     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?br>      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;


ACM-Boy 2008-01-19 16:46 发表评论
]]>
PKU2975 Nimhttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38025.htmlACM-BoyACM-BoyFri, 07 Dec 2007 13:41:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38025.htmlhttp://m.shnenglu.com/ACM-Boy/comments/38025.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38025.html#Feedback3http://m.shnenglu.com/ACM-Boy/comments/commentRss/38025.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/38025.html    因ؓ每次只能从一个堆中取矛_Q所以只要对于每个堆iQ先求出其他所有堆的异或和tempQ再?~Ki-1与这个异或和再进行异或是否ؓ0Q只要ؓ0得CU胜利的Ҏ。自己先是想枚D0~Ki-1Q与tempq行异或。后来感觉没有必要,只要Ki>temp可以了Q因从堆i中取出x个石子,Ki-x异或temp==0 <==> Ki-x==tempQ只要Ki>tempQ就存在Ki-x==temp?br>
#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]对其他所有堆的石子进行异?br>
            if ( stone[i] > temp )
                ans++;
        }
    }
    printf("%d\n", ans);
}

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




ACM-Boy 2007-12-07 21:41 发表评论
]]>
PKU2907 Collecting Beepershttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38019.htmlACM-BoyACM-BoyFri, 07 Dec 2007 11:31:00 GMThttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38019.htmlhttp://m.shnenglu.com/ACM-Boy/comments/38019.htmlhttp://m.shnenglu.com/ACM-Boy/archive/2007/12/07/38019.html#Feedback1http://m.shnenglu.com/ACM-Boy/comments/commentRss/38019.htmlhttp://m.shnenglu.com/ACM-Boy/services/trackbacks/38019.html    因ؓ地图最大只?0×20Q而beeper最多也只有10个,所以可以考虑用深搜,扑ֈ所有可能\径,在其中加一些简单的减枝可以了。v初以Z时Q可最后还?ms。:Q?br>

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;
    }





ACM-Boy 2007-12-07 19:31 发表评论
]]>
޾ƷþþþþðĦ | þҹҹݺ2022 | þ99ƷСѼ | ҹŷƷþþþþþ| þۺϳDž | һһþaþþƷۺ | Ʒþþһ| ھƷþ| þ91Ʒ91þ鶹| þ㽶߿ۿè?v| պһþ99| þþþþëƬѲ| ޹Ʒþþþþ| 18պҹþó | þþþþ޾Ʒ| seguiþùƷ| ˳ɾƷþþþ| þ޾Ʒ벥| þó˾ƷƵ| þۺɫHEZYO| þùֱ| 91Ƶ91þþ| þŮcc98cm| þþƷĻ| 99reþùƷҳ| һþ֪ۺϾþ| ھƷ˾þþþø| þ޹Ʒ| 99þþùƷţ| ۺϾþϵ| þ޾Ʒ| þþƷAVþþ| ޹պŷþ| þþþùɫAVѹۿ| ˾þں2019| ƷŮþþþ| Vþþ| ˾Ʒþ| һõþۺϺݺAV| ɫͷվþ| Ĺ˾Ʒþ޾ƷA뾫Ʒ|