問題 A: 時鐘
題目描述
有一個標準的12小時時鐘,它有一個時針,一個分針。現問你,在給定的兩個時刻之間分針與時針相遇幾次?
輸入
輸入包含多組測試數據。每組輸入包含4個整數,前兩個數字分別表示起始時刻的小時和分,後兩個數字分別表示結束時刻的小時和分。
小時數在[1,12]內,分鐘數在[0,59]內。
注意:
1)輸入中的起始和結束時刻均不會出現時針和分針恰好相遇的情況,例如12點0分。
2)輸入中不會出現起始時刻和結束時刻相同的情況。
3)在時針從起始時刻到結束時刻運轉的過程中,時針轉過的角度一定小於360度。
4)在時針從起始時刻到結束時刻運轉的過程中,時針有可能越過錶盤上12點鐘的刻度。如果越過了,說明起始時刻和結束時刻中一個是A.M.,一個是P.M.。如果沒越過,說明起始時刻和結束時刻都是A.M.或都是P.M.。
輸出
輸出的第一行爲“Initial time Final time Passes”,具體的輸出格式請參照輸出樣例。可用鼠標選中來看出空格數等細節。
樣例輸入
12 50 1 2
3 8 3 20
2 45 11 0
11 0 3 20
1 2 12 50
3 20 3 8
樣例輸出
Initial time Final time Passes
12:50 01:02 0
03:08 03:20 1
02:45 11:00 8
11:00 03:20 4
01:02 12:50 11
03:20 03:08 10
題解:
模擬
從時鐘開始時刻到 終止時刻路程轉化成分鐘,之間相差多少圈基本就相遇幾次。
每12小時相遇11次。 所以時間差*11/720即可。
最後注意一下輸出格式,可用鼠標選中來看出空格數等細節。
代碼:
#include<bits/stdc++.h>
using namespace std;
int main()
{
cout<<"Initial time Final time Passes"<<endl;
int h1, m1, h2, m2;
while(cin>>h1>>m1>>h2>>m2)
{
int s1 = h1, s2 = m1, s3 = h2, s4 = m2;//存儲起始時間
h1 %= 12;
h2 %= 12;
if(h2<h1) h2 += 12;
else if(h2 == h1 && m2<=m1)h2 += 12;
int t1 = (h1*60+m1)*11;
int t2 = (h2*60+m2)*11;//轉化分鐘
int ans = t2/720 - t1/720;//公式
printf(" %02d:%02d %02d:%02d", s1,s2,s3,s4);//注意格式
printf("%8d\n", ans);
}
return 0;
}
問題 B: 舞伴的搭配(partner)
題目描述
學校將要舉行一年一度的文藝匯演,笑笑所在年級決定排練一個舞蹈,爲選擇表演者,老師定下了如下規則:爲了舞蹈的美觀,當且僅當一男一女的身高之差不超過給定的整數c時,這兩個人可以成爲舞伴進行演出。笑笑所在年級共有m名男生和n名女生,給定每個人身高(身高是120到220之間的整數),問最多能有多少對舞蹈者進行演出。
例如,有3名女生和3名男生,女生的身高分別是160釐米、170釐米、180釐米,男生的身高分別爲170釐米、175釐米、185釐米,c=7釐米。那麼最多有2對舞蹈者:可以是女2和男1一組,女3和男2一組,共2組(女1不能和任何男生成爲一組),所以這個情況下2將成爲最後的答案。
輸入
輸入分三行:
第一行三個整數m、n、c,分別表示男生人數、女生人數和身高最大差值。
第二行m個整數,分別表示m個男生的身高。
第三行n個整數,分別表示n個女生的身高。
輸出
僅一個整數,表示舞蹈者組數的最大數目。
樣例輸入
3 3 7
170 185 175
160 170 180
樣例輸出
2
提示
數據規模:
100%數據,滿足m,n≤1000
題解:
貪心
大致思路:男生和女生的身高先排個序,再一個個匹配
但是怎麼匹配呢?
先找男生第一個和女生第一個匹配,
如果身高差>c且男生更矮就下一個男生
如果身高差>c且女生更矮就下一個女生
如果身高差<=c——匹配成功
代碼:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int man[MAXN],woman[MAXN];
int m,n,c;
int main()
{
cin>>m>>n>>c;
for(int i = 1;i <= m; ++i) cin>>man[i];
for(int i = 1;i <= n; ++i) cin>>woman[i];
sort(man + 1,man + 1 + m,cmp);//男生排序
sort(woman + 1,woman + 1 + n,cmp);//女生排序
int num1 = 1,num2 = 1,cnt = 0;
while(num1 <= m && num2 <= n)
{
if(man[num1] - woman[num2] > c) num2++; //如果女生矮
else if(woman[num2] - man[num1] > c) num1++; //如果男生矮
else
{
num1++;
num2++;
cnt++;
}
}
printf("%d\n",cnt);
}
問題 C: 心急的C小加
題目描述
C小加有一些木棒,它們的長度和質量都已經知道,需要一個機器處理這些木棒,機器開啓的時候需要耗費一個單位的時間,如果第i+1個木棒的重量和長度都大於等於第i個處理的木棒,那麼將不會耗費時間,否則需要消耗一個單位的時間。因爲急着去約會,C小加想在最短的時間內把木棒處理完,你能告訴他應該怎樣做嗎?
輸入
第一行是一個整數T(1<T<1500),表示輸入數據一共有T組。
每組測試數據的第一行是一個整數N(1<=N<=5000),表示有N個木棒。接下來的一行分別輸入N個木棒的L,W(0 < L ,W <= 10000),用一個空格隔開,分別表示木棒的長度和質量。
輸出
處理這些木棒的最短時間。
樣例輸入
3
5
4 9 5 2 2 1 3 5 1 4
3
2 2 1 1 2 2
3
1 3 2 2 3 1
樣例輸出
2
1
3
題解:
貪心算法+Dilworth定理
1.將木塊按照長度上升排序,如果,長度相等,那麼,按照重量的大小升序排序。
2.主要是貪心算法+Dilworth定理,因爲,兩個結點之間,當長度和重量都大於前面的結點,那麼,符合我們的要求,所以,可以將已經排序好的序列,分成多個序列,這些序列是按照重量的大小來排序,然後儘可能多的找出符合要求的結點,這裏主要用到了貪心算法。
3.我們只要統計有多少個序列,就是得到的結果。
代碼:
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int l,w;
}data[5005];
int vis[5005];
int T,n;
int cmp(Node a,Node b)
{
if(a.l < b.l)return 1;
else if(a.l == b.l && a.w < b.w)return 1;
return 0;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i = 1;i <= n; ++i)
scanf("%d%d",&data[i].l,&data[i].w);
memset(vis,0,sizeof(vis));
sort(data + 1,data + 1 + n,cmp);
int cnt = 0,zl;
for(int i = 1;i <= n; ++i)
if(!vis[i])
{
cnt++;
zl = data[i].w;
for(int j = i + 1;j <= n; ++j)
if(zl <= data[j].w && !vis[j])
{
vis[j] = 1;
zl = data[j].w;
}
}
printf("%d\n",cnt);
}
return 0;
}
問題 D: 摧毀巴士站
題目描述
Gabiluso是最偉大的間諜之一。現在,他試圖完成一個“不可能完成”的使命――減緩Colugu的軍隊到達機場的時間。Colugu有n個公共汽車站和m條道路。每條道路直接連接兩個巴士站,所有的道路都是單向的。爲了保持空氣潔淨,政府禁止所有軍用車輛,因此,軍隊必須乘搭巴士去機場。兩個巴士站之間,可能有超過一條道路。如果一個公共汽車站被破壞時,所有連接該站的道路將無法運作。Gabiluso需要做的是摧毀了一些公共汽車站,使軍隊無法在K分鐘內到達機場。一輛公交車通過一條道路,都是一分鐘。所有巴士站的編號從1到n。1號巴士站是在軍營,第n號站是機場。軍隊始終從第一站出發。第一站和第n站不能被破壞,這裏有大量的防禦力量。當然也沒有從第一站到第n站的道路。
請幫助Gabiluso來計算能完成使命所需摧毀的最低數目的巴士站。
輸入
第一行包含三個整數n,m,k (2<n<=50,0<m<=4000,0<k<1000)。
接下來m行,每行2個整數s和f,表示從站s到站f有一條路。
輸出
輸出最少需要摧毀的巴士站數目。
樣例輸入
樣例輸出
提示
【數據規模】
30%的數據N<=15。
題解:
遞歸摧毀某個點,然後spfa判斷。但是有些點,可能經過他的路徑,長度都是大於k的,那麼這些點就不必要進行遞歸。於是,我們每次找一次最短路,看看從1~n的最短路分別經過了哪幾個點。因爲這裏面的點都是在不符合條件的最短路里,所以我們遞歸那些經過的點刪或者不刪,直到最短路符合k的條件爲止,取一個刪的數目最少的爲答案即可。
代碼:
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans=1e9;
int a[55][55],dis[55],f[55],g[55][55];
int vis[55],flag[55];
queue<int> Q;
void SPFA()//SPFA模板
{
memset(dis,0x7f,sizeof(dis));
dis[1] = 0;
Q.push(1);
while(!Q.empty())
{
int x = Q.front();
Q.pop();
vis[x] = 0;
for(int i = 1;i <= n; ++i)
if(!flag[i] && a[x][i] && a[x][i]+dis[x] < dis[i])
{
dis[i] = dis[x] + a[x][i];
f[i] = x;
if(!vis[i]) Q.push(i);
}
}
}
void check(int x,int y)//遞歸刪點
{
if(x == 1) return;
check(f[x],y);
g[y][++g[y][0]] = x;
}
void dfs(int x)
{
if(x >= ans) return;
memset(f,0,sizeof(f));
SPFA();//跑最短路
if(dis[n] > k)
{
ans = min(ans,x);
return;
}
g[x][0] = 0;
check(n,x);
for(int i = 1;i < g[x][0]; ++i)
{
flag[g[x][i]] = 1;//標記,意爲刪除此點
dfs(x + 1);
flag[g[x][i]] = 0;//還原現場,回溯
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i = 1;i <= m; ++i)
{
int x,y;
scanf("%d%d",&x,&y);
a[x][y] = 1;
}
dfs(0);
printf("%d\n",ans);
return 0;
}
問題 H: 競技遊戲
題目描述
小灰灰和小東東在玩一種競技遊戲。在遊戲中,小灰灰給小東東由n個正整數組成的序列以及m條操作指令,需要小東東按照指令來對n個整數進行操作。其中每條指令都包括二個整數(a, b),意義如下:
如果a大於0,表示將序列中第b個數乘於2;
如果a小於0,表示將序列中第b個數加上2;
如果a等於0,則忽略此條指令。
遊戲結束後,小東東需要求出序列中的最大值。現在小東東求助於你,希望你能用計算機編程求出他需要的答案。題目保證計算結果在int的表示範圍內。
輸入
輸入數據第一行爲一整數T,表示有T組數據。每組輸入數據第一行有二個整數n, m, (1 <= n <= 100), (1 <= m <= 100), 第二行有n個整數(1 ~100),表示初始序列,編號從1...n。接着是m行表示m條指令,每行共有2個用空格隔開的整數a b,(-50<= a <= 50), (1 <= b <= n)。
輸出
對於每組數據,輸出一個整數佔一行,表示操作後的序列中的最大整數。
樣例輸入
2
2 2
1 2
1 1
-1 2
3 4
1 5 6
1 1
1 1
0 1
-1 1
樣例輸出
4
6
題解:
入門的模擬題
代碼:
#include<bits/stdc++.h>
const int MAXN = 105;
using namespace std;
int T,n,m,a,b;
int Array[MAXN];
int max_ans;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n; ++i)
scanf("%d",&Array[i]);
while(m--)
{
scanf("%d%d",&a,&b);
if(a > 0)
Array[b] *= 2;
else if(a < 0)
Array[b] += 2;
}
max_ans = Array[1];
for(int i = 1;i <= n; ++i)
max_ans = max(max_ans,Array[i]);
printf("%d\n",max_ans);
}
return 0;
}
問題 I: 手機話費
題目描述
小明的手機每天消費1元,每消費K元就可以獲贈1元,一開始小明有M元,問最多可以用多少天?
輸入
輸入包括多個測試實例。每個測試實例包括2個整數M,K(2<=k<=M<=1000)。M=0,K=0代表輸入結束。
輸出
對於每個測試實例輸出一個整數,表示M元可以用的天數。
樣例輸入
2 2
4 3
0 0
樣例輸出
3
5
題解:
語言基礎題
代碼:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int m,k;
while(cin>>m>>k&&m&&k)
{
int a=0;
int count=0;
while(m)
{
m--;
count++;
a++;
if(a==k)
{
m++;
a=0;
}
}
cout<<count<<endl;
}
return 0;
}