當前位置:編程學習大全網 - 行動軟體 - 求程序設計大賽題目

求程序設計大賽題目

壹、行棋遊戲:

這是壹種只有壹個棋子的遊戲。棋盤被分為N行,M列的方格,某個位置被標記為終點T。在任何壹個位置,棋子可以向左、右、上、下四個方向移動壹格,記移動距離為1。

在棋盤上有壹些特殊方格——飛行器,每個飛行器有壹個飛行距離d,棋子達到後可以繼續在同方向再“飛”d格,且移動距離仍然為1。例如,如果棋子在位置(2,8),飛行器在位置(2,7),且飛行距離為5,那麽棋子向左走壹格,將直接到達位置(2,2)且移動距離為1。如果飛行點落在棋盤外,則只能停在邊界上。例如,假若前個飛行器的飛行距離為10,那麽棋子的最終位置是(2,1)。

而且,如果飛行後的落點仍然是飛行器,則將連續飛行到目的地,且中間點不對當前棋子產生影響,當然也不算任何移動距離。例如,如果棋子位置在(2,8),飛行器在(2,7)、(2,5),且飛行距離都是5,此時棋子向左移動壹格,則(2,5)的飛行器將不產生作用,移動距離仍然為1。

妳的任務就是,編程計算出棋子達到終點的最短移動距離。

輸入:

輸入可以有多個測試用例。每個測試用例的第壹行是兩個整數N、M(3<=N, M<=100),表示棋盤的行列數。隨後是壹個整數K,表示飛行器的個數。接著的K行每行有3個正整數x、y、d,分別表示飛行器的位置(x,y)(2 <= x <= N-1, 2 <= y <= M-1)及飛行距離d。最後的兩行第壹行是棋子的初始位置S,第二行是終點位置T。妳可以假設數據總是合法的,S與T、飛行器位置互不相同。輸入0 0時表示結束

輸出:

每個測試用例輸出壹行,即達到終點的最短距離。如果不能達到,則輸出“Impossible”。

二、最少錢幣數:

(這個問題的輸入我感覺特別麻煩,希望給出比較好的輸入方法)

這是壹個古老而又經典的問題。用給定的幾種錢幣湊成某個錢數,壹般而言有多種方式。例如:給定了6種錢幣面值為2、5、10、20、50、100,用來湊15元,可以用5個2元、1個5元,或者3個5元,或者1個5元、1個10元,等等。顯然,最少需要2個錢幣才能湊成15元。

妳的任務就是,給定若幹個互不相同的錢幣面值,編程計算,最少需要多少個錢幣才能湊成某個給出的錢數。

輸入:

輸入可以有多個測試用例。每個測試用例的第壹行是待湊的錢數值M(1 <= M <= 2000,整數),接著的壹行中,第壹個整數K(1 <= K <= 10)表示幣種個數,隨後是K個互不相同的錢幣面值Ki(1 <= Ki <= 1000)。輸入M=0時結束。

輸出:

每個測試用例輸出壹行,即湊成錢數值M最少需要的錢幣個數。如果湊錢失敗,輸出“Impossible”。妳可以假設,每種待湊錢幣的數量是無限多的。

樣例輸入:

15

6 2 5 10 20 50 100

1

1 2

0

樣例輸出:

2

Impossible 最佳答案第壹題,典型的BFS找最短路

#include <iostream>

#define MAXN 105

using namespace std;

const int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

int m,n;

int map[MAXN][MAXN];

int head,tail;

int queue[MAXN*MAXN][3];

bool hash[MAXN][MAXN];

int tx,ty;

int main()

{

while (cin>>n>>m && n>0)

{

int i,j,k;

memset(map,0,sizeof(map));

cin>>k;

while (k--)

{

cin>>i>>j;

i--;

j--;

cin>>map[i][j];

}

memset(hash,true,sizeof(hash));

cin>>queue[0][0]>>queue[0][1];

queue[0][0]--;

queue[0][1]--;

queue[0][2]=0;

hash[queue[0][0]][queue[0][1]]=false;

head=0;

tail=1;

cin>>tx>>ty;

tx--;

ty--;

while (head<tail && hash[tx][ty])

{

for (k=0;k<4;k++)

{

i=queue[head][0]+dir[k][0];

j=queue[head][1]+dir[k][1];

while (i>=0 && i<n && j>=0 && j<m && map[i][j]>0)

{

i+=map[i][j]*dir[k][0];

j+=map[i][j]*dir[k][1];

if (i<0 || i>=n || j<0 || j>=m)

{

if (i<0) i=0;

if (i>=n) i=n-1;

if (j<0) j=0;

if (j>=m) j=m-1;

break;

}

}

if (i>=0 && i<n && j>=0 && j<m)

if (hash[i][j])

{

queue[tail][0]=i;

queue[tail][1]=j;

queue[tail][2]=queue[head][2]+1;

hash[i][j]=false;

if (i==tx && j==ty) cout<<queue[tail][2]<<endl;

tail++;

}

}

head++;

}

if (hash[tx][ty]) cout<<"impossible"<<endl;

}

return 0;

}

第二題是典型的DP

用f[i][j]表示用前i種幣值湊出總額為j的錢所需的最少錢幣個數

狀態轉移方程f[i][j]=min{f[i-1][j](i>0時),f[i][j-Ki]+1(j>=Ki時),無窮大};

#include <iostream>

#define MAXM 2010

#definme MAXK 15

using namespace std;

int m,k;

int K[MAXK];

int f[MAXK][MAXM];

int main()

{

while (cin>>m && m>0)

{

int i,j;

cin>>k;

for (i=1;i<=k;i++) cin>>K[i];

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

f[0][0]=0;

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

for (j=0;j<=m;j++)

{

int min;

min=-1;

if (f[i-1][j]!=-1 && (min==-1 || f[i-1][j]<min)) min=f[i-1][j];

if (j>=K[i] && f[i][j-K[i]]!=-1 && (min==-1 || f[i][j-K[i]]+1<min)) min=f[i][j-K[i]]+1;

f[i][j]=min;

}

if (f[k][m]==-1) cout<<"impossible"<<endl;

else cout<<f[k][m]<<endl;

}

return 0;

}

  • 上一篇:我和書的故事記敘文
  • 下一篇:優酷網裏怎麽搜索用戶?
  • copyright 2024編程學習大全網