NOI是给中学生的精英中的精英设计的... 正好适合普通大学生
ACM是给大学生的精英中的精英设计的... 正好适合超人大学生

女侠,约吗?
45. (数列的最小代价) 给定一个正整数序列,例如:4,1,2,3, 不改变数的位置把
它们相加, 并且由括号来标记每一次加法所得到的和。例如:((4+1)+(2+3))=
((5)+(5))=10. 除去原数4、1、2、3之外,其余都为中间结果,如:5,5,10, 将中
间结果相加,得到:5+5+10=20, 数 20 称为此数列的一个代价。对于另一种算法:
(4+((1+2)+3))=(4+((3+3))=(4+(6))=10, 得到数列的另一个代价为:3+6+10=19.
若给出 N 个数的数列,求出此数列的最小代价。
 程序代码:
程序代码:
#include <iostream>
using namespace std;int *a,**b,**c,n;
void f();
int main()
{
cout<<\"请输入总数N:\"<<endl;
cin>>n;
a=new int[n];
b=new int*[n];
c=new int*[n];
cout<<\"请依次输入\"<<n<<\"个数\"<<endl;
for(int i=0;i<n;i++)
{
b[i]=new int[n];
c[i]=new int[n];
cin>>a[i];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
c[i][j]=0;
i==j?b[i][j]=a[i]:b[i][j]=0;
}
cout<<a[i]<<\" \";
}
cout<<endl;
f();
cout<<\"最小代价为:\"<<c[0][n-1]<<endl;
delete a;
for(int i=0;i<n;i++)
{
delete b[i];
delete c[i];
}
delete b;
delete c;
system(\"pause\");
return 0;
}void f()
{
int x;
for(int k=1;k<n;k++)
for(int i=0;i<n-k;i++)
b[i][i+k]=b[i][i+k-1]+a[i+k];
for(int k=0;k<n;k++)
for(int i=0;i<n-k;i++)
for(int r=0;r<k;r++)
{
x=b[i][i+r]+b[i+r+1][i+k]+c[i][i+r]+c[i+r+1][i+k];
if(x<c[i][i+k]||c[i][i+k]==0)
c[i][i+k]=x;
}
}
[此贴子已经被作者于2007-7-9 17:50:02编辑过]

*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *
 *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
*  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *
 0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0
  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0
*  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0  *  0
Press any key to continue
6.3
#include<iostream.h>
#include<iomanip.h>
void main()
{
    int i=0,j=0;
    int sum=1;
    int left,right,up,down;
    int a[6][6];
    left=0;
    right=0;
    up=0;
    down=1;
    for(i=0;i<6;i++)
        for(j=0;j<6;j++)
            a[i][j]=0;
    i=0;
    j=0;
    while(sum<=36)
    {
        if(down==1)
        {
            if(i<6&&a[i][j]==0)
            {
                a[i][j]=sum;
                i++;
                sum++;
            }
            else
            {
                down=0;
                right=1;
                i--;
                j++;
            }
        }
        else if(right==1)
        {
            if(j<6&&a[i][j]==0)
            {
                a[i][j]=sum;
                j++;
                sum++;
            }
            else
            {
                right=0;
                up=1;
                j--;
                i--;
            }
        }
        else if(up==1)
        {
            if(i>=0&&a[i][j]==0)
            {
                a[i][j]=sum;
                i--;
                sum++;
            }
            else
            {
                left=1;
                up=0;
                i++;
                j--;
            }
        }
        else if(left==1)
        {
            if(j>=0&&a[i][j]==0)
            {
                a[i][j]=sum;
                j--;
                sum++;
            }
            else
            {
                left=0;
                down=1;
                j++;
                i++;
            }
        
        }
    }
    for(i=0;i<6;i++)
    {
        for(j=0;j<6;j++)
            cout<<setw(5)<<a[i][j];
        cout<<endl;
    }
}
/*---------------------------------------------------------------------------
File name:      C76-14.cpp
Author:         HJin (email: fish_sea_bird [at] yahoo [dot] com)
Created on:     7/3/2007 17:18:43
Environment:    Windows XP Professional SP2 English +
                Visual Studio 2005 v8.0.50727.762
Modification history:
===========================================================================
Problem statement:
---------------------------------------------------------------------------
经典 76 道编程题 之 14:
14. 有黑白棋子各有 N 个(分别用*和O代替),按下图方式排列
     ***...***OOO...OOO
         N个黑棋            N个白棋
允许将相邻两个棋子互换位置,最后使队形成黑白交替排列,试编程实现该操作。
Analysis:
---------------------------------------------------------------------------
We are only allowed to swap to adjacent stones. This can be done as follows:
    move N+1st white stone to position 2*1 (position 1 is untouched)
        N-1 swaps needed;
    move N+2nd white stone to position 2*2 (positions 1 to 3 are untouched)
        N-2 swaps needed;
    move N+3rd white stone to position 2*3 (positions 1 to 5 are untouched)
        N-3 swaps needed;
......
    move N+(N-1)st white stone to position 2(N-1) (positions 1 to 2*N-3 are untouched)
        1 swap needed;
Totally, we need
        
    (N-1) + (N-2) +... + 1 = N*(N-1)/2 swaps.
Sample output:
---------------------------------------------------------------------------
(n=6)
Step #1:        * * * * * O * O O O O O
Step #2:        * * * * O * * O O O O O
Step #3:        * * * O * * * O O O O O
Step #4:        * * O * * * * O O O O O
Step #5:        * O * * * * * O O O O O
Step #6:        * O * * * * O * O O O O
Step #7:        * O * * * O * * O O O O
Step #8:        * O * * O * * * O O O O
Step #9:        * O * O * * * * O O O O
Step #10:       * O * O * * * O * O O O
Step #11:       * O * O * * O * * O O O
Step #12:       * O * O * O * * * O O O
Step #13:       * O * O * O * * O * O O
Step #14:       * O * O * O * O * * O O
Step #15:       * O * O * O * O * O * O
* O * O * O * O * O * O
number of steps is 15.
Press any key to continue . . .
Reference:
---------------------------------------------------------------------------
1. 野比, [全民编程]76道高难度C++练习题
https://bbs.bc-cn.net/viewthread.php?tid=147967
*/
#include <iostream>
#include <fstream>
using namespace std;
/**
Swap function.
*/
inline void swap(char& a, char &b);
/**
O(n^2) algorithm.
@param n --- number of black stones. Number of Total stones is n+n = 2*n.
@param numSwaps --- reference to keep record of how many steps we used. For this
                    algo, the number is n*(n-1)/2 = combination(n, 2).
@param showIntermediateSteps --- do you want to show intermediate steps?
                                 Yes = show it,
                                 No = don't show it.
@param os --- output stream. It defaults to stdout.
*/
void exchange(int n, int& numSwaps, 
              bool showIntermediateSteps = true,
              std::ostream& os = cout);
int main()
{
    int n=6;
    int numSwaps;
    std::ofstream ofs("C76-14-Answer.txt");
    if(!ofs)
    {
        cout<<"cannot open file C76-14-Answer.txt.\n";
        exit(0);
    }
    exchange(6, numSwaps);
    exchange(6, numSwaps, true, ofs);
cout<<"number of steps is "<<numSwaps<<"."<<endl;
    ofs.close();
    return 0;
}
void swap(char& a, char &b)
{
    char temp =a;
    a = b;
    b = temp;
}
void exchange(int n, int& numSwaps,
              bool showIntermediateSteps,
              std::ostream& os)
{
    char *a = new char[2*n];
    int i;
    int j;
    int k;
    numSwaps = 0;
    for(i=0; i<n; ++i)
    {
        a[i] = '*';
    }
    for(i=n; i<2*n; ++i)
    {
        a[i] = 'O';
    }
    for(i=0; i<=n-2; ++i)
    {
        for(j=n+i; j>=2*(i+1); --j)
        {
            swap(a[j], a[j-1]);
            ++numSwaps;
            if(showIntermediateSteps)
            {
                os<<"Step #"<<numSwaps<<":\t";
                for(k=0; k<2*n; ++k)
                {
                    os<<a[k]<<" ";
                }
                os<<endl;
            }
        }
    }
    // show final result
    os<<endl;
    for(k=0; k<2*n; ++k)
    {
        os<<a[k]<<" ";
    }
    os<<endl;
    delete [] a;
}

/*---------------------------------------------------------------------------
File name:      C76-18.cpp
Author:         HJin (email: fish_sea_bird [at] yahoo [dot] com)
Created on:     7/3/2007 17:18:43
Environment:    Windows XP Professional SP2 English +
                Visual Studio 2005 v8.0.50727.762
Modification history:
===========================================================================
Problem statement:
---------------------------------------------------------------------------
经典 76 道编程题 之 18:
18. 在一线性七个格位置的图上有两种不同颜色的棋子 A,B. 排列如下图所示,中间
格的位置为空。
       ┎─┰─┰─┰─┰─┰─┰─┒
       ┃A ┃A ┃ A┃  ┃B ┃B ┃B ┃
       ┖─┸─┸─┸─┸─┸─┸─┚
要求将 A,B 的现行位置交换,形成下图中的排列:
       ┎─┰─┰─┰─┰─┰─┰─┒
       ┃B ┃B ┃B ┃  ┃A ┃A ┃A ┃
       ┖─┸─┸─┸─┸─┸─┸─┚
移动棋子的条件:
(1) 每个格中只准放一个棋子。
(2) 任意一个棋子均可移动一格放入空格内。(You can move both forward and backward.)
(3) 一方的棋子均可跳过另一方的一个棋子进入空格。
(4) 任何棋子不得跳跃两个或两个以上棋子(无论颜色同异)
(5) 任何一个颜色棋子只能向前跳,不准向后跳。(You can only leap forward.)
编程完成有关的移动,并且完成具有2N+1个格子的情形. 其中两种颜色各有
N个棋子,且中间为空格.
Analysis:
---------------------------------------------------------------------------
Move 1st B to the front, then move the blank back to 2nd B;
Move 2nd B to the next front, then move the blank back to 3rd B;
...
Repeat until we are done.
This algorithm needs 3*n^2 number of moves, where n is the number of
B stones. I think the algorithm is optimal, I don't prove it though.
Sample output:
---------------------------------------------------------------------------
Step #0:        AAAAA BBBBB
Step #1:        AAAAAB BBBB
Step #2:        AAAA BABBBB
Step #3:        AAAAB ABBBB
Step #4:        AAA BAABBBB
Step #5:        AAAB AABBBB
Step #6:        AA BAAABBBB
Step #7:        AAB AAABBBB
Step #8:        A BAAAABBBB
Step #9:        AB AAAABBBB
Step #10:        BAAAAABBBB
Step #11:       B AAAAABBBB
Step #12:       BA AAAABBBB
Step #13:       BAA AAABBBB
Step #14:       BAAA AABBBB
Step #15:       BAAAA ABBBB
Step #16:       BAAAAA BBBB
Step #17:       BAAAAAB BBB
Step #18:       BAAAA BABBB
Step #19:       BAAAAB ABBB
Step #20:       BAAA BAABBB
Step #21:       BAAAB AABBB
Step #22:       BAA BAAABBB
Step #23:       BAAB AAABBB
Step #24:       BA BAAAABBB
Step #25:       BAB AAAABBB
Step #26:       B BAAAAABBB
Step #27:       BB AAAAABBB
Step #28:       BBA AAAABBB
Step #29:       BBAA AAABBB
Step #30:       BBAAA AABBB
Step #31:       BBAAAA ABBB
Step #32:       BBAAAAA BBB
Step #33:       BBAAAAAB BB
Step #34:       BBAAAA BABB
Step #35:       BBAAAAB ABB
Step #36:       BBAAA BAABB
Step #37:       BBAAAB AABB
Step #38:       BBAA BAAABB
Step #39:       BBAAB AAABB
Step #40:       BBA BAAAABB
Step #41:       BBAB AAAABB
Step #42:       BB BAAAAABB
Step #43:       BBB AAAAABB
Step #44:       BBBA AAAABB
Step #45:       BBBAA AAABB
Step #46:       BBBAAA AABB
Step #47:       BBBAAAA ABB
Step #48:       BBBAAAAA BB
Step #49:       BBBAAAAAB B
Step #50:       BBBAAAA BAB
Step #51:       BBBAAAAB AB
Step #52:       BBBAAA BAAB
Step #53:       BBBAAAB AAB
Step #54:       BBBAA BAAAB
Step #55:       BBBAAB AAAB
Step #56:       BBBA BAAAAB
Step #57:       BBBAB AAAAB
Step #58:       BBB BAAAAAB
Step #59:       BBBB AAAAAB
Step #60:       BBBBA AAAAB
Step #61:       BBBBAA AAAB
Step #62:       BBBBAAA AAB
Step #63:       BBBBAAAA AB
Step #64:       BBBBAAAAA B
Step #65:       BBBBAAAAAB
Step #66:       BBBBAAAA BA
Step #67:       BBBBAAAAB A
Step #68:       BBBBAAA BAA
Step #69:       BBBBAAAB AA
Step #70:       BBBBAA BAAA
Step #71:       BBBBAAB AAA
Step #72:       BBBBA BAAAA
Step #73:       BBBBAB AAAA
Step #74:       BBBB BAAAAA
Step #75:       BBBBB AAAAA
n   # of steps  3*n^2
----------------------------------
1   3           3
2   12          12
3   27          27
4   48          48
5   75          75
6   108         108
7   147         147
8   192         192
9   243         243
10  300         300
11  363         363
12  432         432
13  507         507
14  588         588
15  675         675
16  768         768
17  867         867
18  972         972
19  1083        1083
20  1200        1200
21  1323        1323
22  1452        1452
23  1587        1587
24  1728        1728
25  1875        1875
26  2028        2028
27  2187        2187
28  2352        2352
29  2523        2523
30  2700        2700
31  2883        2883
32  3072        3072
33  3267        3267
34  3468        3468
35  3675        3675
36  3888        3888
37  4107        4107
38  4332        4332
39  4563        4563
Press any key to continue . . .
Reference:
---------------------------------------------------------------------------
1. 野比, [全民编程]76道高难度C++练习题
https://bbs.bc-cn.net/viewthread.php?tid=147967
*/
#include <iostream>
#include <iomanip>
using namespace std;
char* a; // 1d buffer
int n; // number of A stones
void swap(char&a, char&b);
/**
Move stone B to  the front. Note that the front is incrementing.
*/
void moveBToFront(int front, int& counter, bool bShowSteps = true);
/**
Move the blank so that it is directly before next B.
*/
void moveBlank(int front, int& counter, bool bShowSteps = true);
/**
Simulate the moves.
@param bShowSteps = true means we show all the steps,
                  = false means we show no steps.
*/
int play(bool bShowSteps = true);
/**
Print the buffer.
*/
void print(int counter);
int main()
{
    // test #1
    n = 5;
    play();
    // test #2
    cout<<"\n\nn   # of steps  3*n^2\n";
    cout<<"----------------------------------\n";
    for(n=1; n<40; ++n)
    {
        cout<<setw(4)<<std::left<<n<<setw(12)<<play(false)<<3*n*n<<endl;
    }
    return 0;
}
void swap(char&a, char&b)
{
    char temp = a;
    a = b;
    b = temp;
}
void print(int counter)
{
    cout<<"Step #"<<counter<<":\t";
    for(int i=0; i<=2*n; ++i)
    {
        cout<<a[i];
    }
    cout<<endl;
}
int play(bool bShowSteps)
{
    int j;
    int counter = 0;
    int front = 0;
    // fill in the initial status of the stones
    a = new char[2*n+1];
    for(j=0; j<n; ++j)
    {
        a[j] = 'A';
    }
    a[n] = ' ';
    for(j=n+1; j<=2*n; ++j)
    {
        a[j] = 'B';
    }
    if(bShowSteps)
    {
        print(counter);
    }
    while(front<n-1)
    {
        // move B to front
        moveBToFront(front, counter, bShowSteps);
        // move the blank before next B
        moveBlank(front+1, counter, bShowSteps);
        ++front; // update front
    }
    // The blank is before last B, so we need to
    // move last B to front.
    moveBToFront(front, counter, bShowSteps);
    // free memory
    delete [] a;
    return counter;
}
void moveBToFront(int front, int& counter, bool bShowSteps)
{
    char temp;
    int j = n +front;
    while(j>front)
    {
        // move B to the blank (backwards)
        temp = a[j+1];
        a[j+1] = ' ';
        a[j] = temp;
        ++counter;
        
        if(bShowSteps)
        {
            print(counter);
        }
        // leap A to the blank (forward)
        a[j+1] = a[j-1];
        a[j-1] = ' ';
        ++counter;
        if(bShowSteps)
        {
            print(counter);
        }
        --j;
    }
    // one more time --- move B to front
    temp = a[j+1];
    a[j+1] = ' ';
    a[j] = temp;
    ++counter;
    if(bShowSteps)
    {
        print(counter);
    }
}
void moveBlank(int front, int& counter, bool bShowSteps)
{
    char temp;
    int j = front;
    // move the blank so that it is direclty before next B
    while(j<n+front)
    {
        // move the blank forward
        temp = a[j+1];
        a[j+1] = ' ';
        a[j] = temp;
        ++counter;
        if(bShowSteps)
        {
            print(counter);
        }
        ++j;
    }
}
[此贴子已经被作者于2007-7-15 6:48:53编辑过]

/*---------------------------------------------------------------------------
File name:      C76-33.cpp
Author:         HJin (email: fish_sea_bird [at] yahoo [dot] com)
Created on:     7/3/2007 17:18:43
Environment:    Windows XP Professional SP2 English +
                Visual Studio 2005 v8.0.50727.762
Modification history:
===========================================================================
Problem statement:
---------------------------------------------------------------------------
经典 76 道编程题 之 33:
33. ( 野人与传教士 ) 设有三个传教士和三个野人来到河边,打算乘一只船从右
岸渡到左岸去。该船最大负载能力为两人,在任何时候,如果野人人数超过传教士
人数,那么野人就会把传教士吃掉。他们怎样才能用这条船安全地把所有人都渡过
河去呢?
Analysis:
---------------------------------------------------------------------------
c --- 传教士
y --- 野人
r --- right bank
l --- left bank
b --- boat
The first time we have 1 c and 1 y on the boat and drop the y, let the c come
back to pick up another y;
from 2nd time, 1 y is always on the boat (i.e., either 1y 1c on the boat or 2y
on the boat) and let y do the transfer job.
...
Repeat until all is done. (the last few steps are a little bit different.)
Totally times to use the boat is 4*n-3.
Sample output:
---------------------------------------------------------------------------
Please input number of barbarians n (n>0): 7
#   right bank          boat   left bank
-------------------------------------------------
0   c (7), y (7)
1   c (6), y (6)        cy-->
2   c (6), y (6)        <--c*  y (1)
3   c (6), y (5)        cy-->  y (1)
4   c (6), y (5)        <--y*  c (1), y (1)
5   c (5), y (5)        cy-->  c (1), y (1)
6   c (5), y (5)        <--y*  c (2), y (1)
7   c (5), y (4)        cy-->  c (1), y (2)
8   c (5), y (4)        <--y*  c (2), y (2)
9   c (4), y (4)        cy-->  c (2), y (2)
10  c (4), y (4)        <--y*  c (3), y (2)
11  c (4), y (3)        cy-->  c (2), y (3)
12  c (4), y (3)        <--y*  c (3), y (3)
13  c (3), y (3)        cy-->  c (3), y (3)
14  c (3), y (3)        <--y*  c (4), y (3)
15  c (3), y (2)        cy-->  c (3), y (4)
16  c (3), y (2)        <--y*  c (4), y (4)
17  c (2), y (2)        cy-->  c (4), y (4)
18  c (2), y (2)        <--y*  c (5), y (4)
19  c (2), y (1)        cy-->  c (4), y (5)
20  c (2), y (1)        <--y*  c (5), y (5)
21  c (1), y (1)        cy-->  c (5), y (5)
22  c (1), y (1)        <--y*  c (6), y (5)
23  y (1)               yc-->  c (6), y (5)
24  y (1)               <--y*  c (7), y (5)
25                      yy-->  c (7), y (5)
26                             c (7), y (7)
Press any key to continue . . .
Reference:
---------------------------------------------------------------------------
1. 野比, [全民编程]76道高难度C++练习题
https://bbs.bc-cn.net/viewthread.php?tid=147967
*/
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
using namespace std;
/**
The travel plan.
-->yc going from right bank to left bank
      (1 y and 1 c are on the boat)
<--y* going from right bank to left bank
      (1 y is on the boat, another seat on the boat is empty.
      * --- represents an empty seat.)
@param n --- number of 野人
Totally, we need to use the boat 4*n-3 times, n>=1.
*/
int travel(int n);
/**
Print the status of right bank, boat, and the left left bank.
@param rc --- number of 传教士 on right bank
@param ry --- number of 野人 on right bank
@param b --- tells you who is on the boat
@param lc --- number of 传教士 on left bank
@param ly --- number of 野人 on left bank
*/
void print(int rc, int ry, string b, int lc, int ly, int counter);
int main()
{
    int n;
    cout<<"Please input number of barbarians n (n>0): ";
    cin>>n;
    
    travel(n);
    return 0;
}
int travel(int n)
{
    int rc = n;
    int ry = n;
    string b;
    int lc = 0;
    int ly = 0;
    int i;
    int counter = 0;
    string rightBank;
    string leftBank;
    stringstream oss;
    cout<<"#   right bank          boat   left bank\n";
    cout<<"-------------------------------------------------\n";
    print(rc, ry, "     ", lc, ly, counter);
    if(n==1) // n = 1 is a special case
    {    
        ++counter;
        print(0, 0, "cy-->", 0, 0, counter);
        ++counter;
        print(n-1, n-1, "     ", 1, 1, counter);
        return 1;
    }
    // first few steps
    ++counter;
    print(n-1, n-1, "cy-->", 0, 0, counter);
    ++counter;
    print(n-1, n-1, "<--c*", 0, 1, counter);
    // middle steps
    for(i=1; i<=n-2; ++i)
    {
        ++counter;
        print(n-i,  n-i-1, "cy-->", i-1, i, counter);
        ++counter;
        print(n-i, n-i-1, "<--y*", i, i, counter);
        ++counter;
        print(n-i-1, n-i-1, "cy-->", i, i, counter);
        ++counter;
        print(n-i-1, n-i-1, "<--y*", i+1, i, counter);
    }
    
    // final steps
    ++counter;
    print(0, 1, "yc-->", n-1, n-2, counter);
    ++counter;
    print(0, 1, "<--y*", n, n-2, counter);
    ++counter;
    print(0, 0, "yy-->", n, n-2, counter);
    ++counter;
    print(0, 0, "     ", n, n, counter);
    return counter-1;
}
void print(int rc, int ry, string b, int lc, int ly, int counter)
{
    ostringstream oss;
    string rightBank;
    string leftBank;
cout<<std::left<<setw(4)<<counter<<setw(20);
    if(rc >0)
    {
        oss<<"c (";
        oss<<rc;
        oss<<"), ";
    }
    
    if(ry > 0)
    {
        oss<<"y (";
        oss<<ry;
        oss<<")";
        rightBank = oss.str();
        cout<<rightBank;
    }
    if(ry + rc == 0)
    {
        cout<<" ";
    }
cout<<setw(7)<<b;
oss.str("");
    if(lc >0)
    {
        oss<<"c (";
        oss<<lc;
        oss<<"), ";
    }
    
    if(ly > 0)
    {
        oss<<"y (";
        oss<<ly;
        oss<<")";
        leftBank = oss.str();
        cout<<leftBank;
    }
    cout<<endl;
}
