本文使用Python實現『顏色提取』功能,構建『簡單提取器』與『複雜提取器』,從單個或多個圖像的某個位置提取顏色,類似PS或者PPT中的取色器功能。 ...
【例1】時針分針與秒針
問題描述
給定一個24小時格式的數字時間,問給定的這個時刻時針與分針、時針與秒針、分針與秒針 之間的夾角分別是多少?
輸入
有T(1≤T≤104)組測試用例。
對於每組測試用例,用一行hh:mm:ss描述給定的時間。0≤hh<24,0≤mm<60,0≤ss<60。
輸出
對於每組測試用例,輸出像A/B這樣的實數。(A和B是互質的)。如果它是一個整數,那麼就直接輸出它。描述時針和分針、時針和秒針、分針和秒針之間的角度。
輸入樣例
4
00:00:00
06:00:00
12:54:55
04:40:00
輸出樣例
0 0 0
180 180 0
1391/24 1379/24 1/2
100 140 120
(1)編程思路。
將表盤的0點(或12點)作為起點,整個表盤轉一圈360度,用60個刻度線分成60格,每1格就是6度。
時鐘每走1個小時,時針走5格,轉30度;分針走60格,轉360度(正好走一圈,相當轉0度);秒針走3600格,轉21600度(走了60圈,也相當轉0度)。
時鐘每走1分鐘,分針走1格,轉6度;時針走5/60格,轉1/2度;秒針走60格,相當轉了0度。
時鐘每走1秒,秒針走1格,轉6度;分針走1/60格,轉1/10度;時針走5/3600格,相當轉了1/120度。
因此,對於任意一個時刻hh:mm:ss,有
時針轉的度數為 30*hh + 1/2*mm + 1/120*ss
分針轉的度數為 6*mm + 1/10*ss
秒針轉的度數為 6*ss
計算出各指針轉的度數後,它們之間的差值就是它們的夾角。
由於計算時有分數比1/120,將它們都乘以120(相當於通分,分母為120),這樣只看各分子部分。有
時針轉的度數為 3600*hh + 60*mm + ss
分針轉的度數為 720*mm + 12*ss
秒針轉的度數為 720*ss
(2)源程式。
#include <stdio.h> int gcd(int a,int b) { if (a%b==0) return b; else return gcd(b,a%b) ; } void output(int a,int b) // 計算圓盤上轉過a度和b度的兩指針之間的夾角並輸出 { int x; x=a>b? a-b:b-a ; if (x % 120 == 0) { x /= 120 ; x %= 360 ; if (x%360 == 0 ) printf("0 ") ; else if (x%180 == 0 ) printf("180 ") ; else printf("%d ", x<180?x:360-x) ; } else { x=x%43200; if (x>43200-x) // 通分後,圓盤一周360度變成 43200度(360*120) x=43200-x; int k = gcd(x,120) ; printf("%d/%d ", x/k, 120/k) ; } } int main() { int t; scanf("%d",&t); while (t--) { int h,m,s,x,y,z; scanf("%d:%d:%d", &h, &m, &s) ; x = 3600*h + 60*m + s ; y = 720*m + 12*s ; z = 720*s ; output(x,y); output(x,z); output(y,z); printf("\n") ; } return 0; }
將上面的源程式提交給HDU 題庫 HDU 5387 Clock (http://acm.hdu.edu.cn/showproblem.php?pid=5387),可以Accepted。
將上面的源程式略作修改,還可以提交給 HDU 2076 夾角有多大 (http://acm.hdu.edu.cn/showproblem.php?pid=2076)。
【例2】時針與分針的夾角
問題描述
給定一個時間HH:MM:SS和一個參數a,請你計算滿足以下條件的下一個時間:
1.時針和分針形成的角度是a。
2.時間可以不是整數,但向下舍入。例如12:34:56.78向下舍入為12:34:56。
輸入
輸入包含多個測試用例。
每個測試用例包含兩行。
第一行是時間HH:MM:SS(0≤HH<12,0≤MM<60,0≤SS<60)。
第二行包含一個整數a(0≤a≤180).
輸出
對於每個測試用例,輸出一行包含測試用例編號和答案HH:MM:SS。
輸入樣例
0:59:59
30
01:00:00
30
輸出樣例
Case #1: 01:00:00
Case #2: 01:10:54
(1)編程思路。
對給定的時間,一秒一秒的加1(向前走一秒到下一個時間)進行枚舉,每次枚舉一個時間,計算時針與分針的夾角r,若r正好等於a,輸出當前時間並結束枚舉。若r不是正好等於a,則輸出找到的第1個形成夾角大於a的前一秒。為此,程式中用pr保存前1秒時間(ph:pm:ps)指針與分針的夾角,這樣當前一秒的夾角pr小於a,但後一秒的夾角大於a,即pr!=a && (pr-a)*(r-a)<0時,輸出前1秒時間ph:pm:ps即可。
(2)源程式。
#include <stdio.h> int main() { int iCase=0; int h,m,s; while (scanf("%d:%d:%d",&h,&m,&s)!=EOF) { int a; scanf("%d", &a) ; int ph=h,pm=m,ps=s; double r,pr; pr=(3600*h + 60*m + s-720*m - 12*s+43200)%43200/120.0; if (pr > 180) pr=360-pr; while (1) { s++; if (s>=60) { s=s%60; m++; if (m>=60) { m=0; h=(h+1)%12; } } r=(3600*h + 60*m + s-720*m - 12*s+43200)%43200/120.0; if (r > 180) r=360-r; if (r==a) { printf("Case #%d: %02d:%02d:%02d\n",++iCase,h,m,s); break; } else if (pr!= a && (r-a) * (pr-a) < 0) { printf("Case #%d: %02d:%02d:%02d\n",++iCase,ph,pm,ps); break; } pr=r; ph=h; pm=m; ps=s; } } return 0; }
將上面的源程式提交給HDU 題庫 HDU 5705 Clock (http://acm.hdu.edu.cn/showproblem.php?pid=5705),可以Accepted。
【例3】時間復現
問題描述
小明有一個鐘錶,當前鐘錶指向了某一個時間。
又有一些很重要的時刻,小明想要在鐘錶上復現這些時間(並不需要依次復現)。我們可以順時針轉動秒針,也可以逆時針轉動秒針,分針和時針都會隨著秒針按規則轉動,小明想知道秒針至少轉動多少角度可以使每個時刻至少都會被訪問一次。
註意,時鐘上的一種時針分針秒針的組合,可以代表兩個不同的時間。
輸入
第一行一個整數 n 代表有多少個時刻要訪問。
第二行三個整數 h,m,s 分別代表當前時刻的時分秒。
最後n行每一行三個整數 hi,mi,si 代表每個要訪問的時刻的時分秒。
1 ≤ n ≤ 86, 400
0 ≤ h, hi < 24
0 ≤ m, mi, s, si < 60
輸出
輸出一行一個數代表秒鐘轉的角度,答案保留兩位小數。
輸入樣例
1
0 1 0
0 1 1
輸出樣例
6.00
(1)編程思路。
我們知道,每小時有3600秒,每分鐘有60秒,每秒秒針轉6度。因此,對於任意一個時刻hh:mm:ss來說,秒針一共會順時針轉(hh * 3600 + mm * 60 + ss)*6 度。
先求出需要每個復現的時間相對當前時間需要順時針轉過的度數,並保存到數組rotate中。在將數組按照轉過的度數從小到大排序,即最小轉過的角度保存在rotate[1]中,最大轉過的角度保存在rotate[N]中。排序後,要復現N個時刻。可以在以下四種情況中取最小值即可。
① 秒針只順時針走。走到需要轉過的最大角度rotate[N]即可。
② 秒針只逆時針走。走到需要轉過的最小角度rotate[1]即可,由於是逆時針旋轉,實際轉過的角度等於aRound-rotate[1]。aRound為時鐘上時針轉完整一圈,秒針需要轉的度數360*60*12。
③ 先順時針走到某個角度rotate[i],再逆時針走到其下一個角度rotate[i+1]。此時,秒針實際轉過的度數為 rotate[i] * 2 + (aRound - rotate[i + 1])。
④ 逆時針走到某個角度rotate[i],再順時針走到其前一個角度rotate[i-1]。此時,秒針實際轉過的度數為 rotate[i-1] + (aRound - rotate[i])*2。
(2)源程式。
#include <stdio.h> #include <algorithm> using namespace std; #define aRound 360 * 60 * 12 // 時針轉一整圈(12小時),秒針轉過的度數 int main() { int n; while (scanf("%d", &n)!=EOF) { int h,m,s,nowrot,tt; scanf("%d%d%d", &h, &m, &s); if (h >= 12) h -= 12; nowrot = (h * 3600 + m * 60 + s)*6; // 當前時刻秒針轉過的度數 int i,rotate[86405]; // 保存各時刻從當前時刻起 秒針順時針轉過的度數 for (i = 1; i <= n; i++) { scanf("%d%d%d", &h, &m, &s); if (h >= 12) h -= 12; tt = (h * 3600 + m * 60 + s)*6; rotate[i] = tt - nowrot; if (rotate[i] < 0) rotate[i] += aRound; } sort(rotate + 1, rotate + n + 1); // 將各時刻秒針轉過的度數從小到大排序 int ans = aRound + 1000000; rotate[0] = aRound; rotate[n + 1] = aRound; if (ans>rotate[n]) ans=rotate[n]; // 秒針一直順時針轉過最大度數 if (ans>aRound-rotate[1]) ans=aRound-rotate[1]; // 秒針一直逆時針轉過最小度數 for (i = 1; i <= n; i++) // 先順時針轉到某個度數,再逆時針轉到其下一個度數 { tt=rotate[i] * 2 + (aRound - rotate[i + 1]); if (ans>tt) ans=tt; } for (i = 1; i <= n; i++) // 先逆時針轉到某個度數,再順時針轉到其下一個度數 { tt=rotate[i-1] + (aRound - rotate[i])*2; if (ans>tt) ans=tt; } printf("%d.00\n", ans); } return 0; }
將上面的源程式提交給HDU 題庫 HDU 6551 Clock (http://acm.hdu.edu.cn/showproblem.php?pid=6551),可以Accepted。
【例4】時鐘
問題描述
從a點b分到s點t分時針和分針重合多少次?
輸入
有多組數據,每組1行4個數 a,b,s,t. 1<=a,s <=12, 0<=b,t<60。0 0 0 0結束。
輸出
每組測試用例,用1行輸出一個整數,表示分針與時針的相遇次數。
輸入樣例
12 50 1 2
3 8 3 20
2 45 11 0
11 0 3 20
1 2 12 50
3 20 3 8
0 0 0 0
輸出樣例
0
1
8
4
11
10
(1)編程思路。
本題主要看分針(相對時針)在這個時間段內可以迴圈多少圈,每迴圈一圈就是相遇一次。
設初始時為00:00,此時分針與時針重合在一起。之後時針在走,分針也在走。每次分針比時針多走一圈,它們就會相遇一次(重合在一起一次)。
對於任意一個時間hh:mm,我們需要計算分針相比時針多走幾圈。
我們知道,12個小時,時針正好走1圈,而分針走了12圈(每1小時走1圈),相比時針,分針多走了12-1=11圈。也就是說在12小時(也是720分鐘)內,時針與分針會重合11次。即1分鐘會多走 11/720圈。
對於時間hh:mm,分針比時針多走的圈數為 (hh*60+mm)*11/720。
兩個時間的圈數差,就是這個時間段內分針與時針的相遇次數。
(2)源程式。
#include <stdio.h> int main() { int a,b,s,t,ans; while (scanf("%d%d%d%d",&a,&b,&s,&t) && (a || b || s || t)) { a=a%12; s=s%12; int s1=(a*60+b)*11; int s2=(s*60+t)*11; if (s2<s1) s2+=720*11; ans=s2/720-s1/720; // 兩個時間的圈數差就是它們的相遇次數 if (s1==0) ans++; // 出發時相遇加1 printf("%d\n",ans); } return 0; }
將上面的源程式提交給HDU 題庫 HDU 2180 時鐘 (http://acm.hdu.edu.cn/showproblem.php?pid=2180),可以Accepted。
在理解了時鐘上時針、分針和秒針轉動規律的基礎上,可以將HDU題庫中如下的幾道題目作為練習。
【練習1】HDU Clock (http://acm.hdu.edu.cn/showproblem.php?pid=1209)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 按照時針與分針的夾角大小來排序 #include <stdio.h> typedef struct { int h,m; double r; // 時針與分針的夾角 }Node; int cmp(Node x,Node y) { if (x.r!=y.r) return x.r>y.r; if (x.h!=y.h) return x.h>y.h; return x.m>y.m; } double fabs(double x) { return x>0?x:-x; } int main() { int t; scanf("%d",&t); while (t--) { Node a[5],temp; int i,j; for (i = 0;i<5;i++) { scanf("%d:%d",&a[i].h,&a[i].m); if (a[i].h>12) a[i].r = fabs(30.0*(a[i].h-12)+a[i].m/2.0-6.0*a[i].m); else a[i].r = fabs(30.0*a[i].h+a[i].m/2.0-6.0*a[i].m); if (a[i].r>180) a[i].r = 360-a[i].r; } for (i=0;i<5-1;i++) for (j=0;j<5-1-i;j++) if (cmp(a[j],a[j+1])) { temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } printf("%02d:%02d\n",a[2].h,a[2].m); } return 0; }參考程式
【練習2】HDU 1371 Clock (http://acm.hdu.edu.cn/showproblem.php?pid=1371)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { printf("Program 3 by team X\n"); printf("Initial time Final time Passes\n"); int a,b,s,t,ans; while (scanf("%d%d%d%d",&a,&b,&s,&t)!=EOF) { printf(" %02d:%02d %02d:%02d",a,b,s,t); a=a%12; s=s%12; int s1=(a*60+b)*11; int s2=(s*60+t)*11; if (s2<s1) s2+=720*11; ans=s2/720-s1/720; // 兩個時間的圈數差就是它們的相遇次數 if (s1==0) ans++; // 出發時相遇加1 printf("%8d\n",ans); } printf("End of program 3 by team X\n"); return 0; }參考程式
【練習3】HDU 1393 Weird Clock (http://acm.hdu.edu.cn/showproblem.php?pid=1393)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { int s,d; while (scanf("%d%d",&s,&d) && (s||d)) { if (s >= 60) s %= 60; int count = 0,flag = 1; while (s) { s += s*d; s %= 60; if(count > 1000) { flag = 0; break; } count++; } if (flag) printf("%d\n",count); else printf("Impossible\n"); } return 0; }參考程式
【練習4】HDU 2395 Alarm Clock (http://acm.hdu.edu.cn/showproblem.php?pid=2395)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <string.h> int calc(int a,int b,int mod) { int ans1,ans2; ans1=(a-b+mod)%mod; ans2=(b-a+mod)%mod; return ans1<ans2?ans1:ans2; } int main() { int t; scanf("%d",&t); while (t--) { char s1[8],s2[8]; scanf("%s %s",s1,s2); int h1,m11,m12,h2,m21,m22; char c1,c2; if (s1[1]==':') { h1=s1[0]-'0'; m11=s1[2]-'0'; m12=s1[3]-'0'; c1=s1[4]; } else { h1=(s1[0]-'0')*10+(s1[1]-'0'); m11=(s1[3]-'0'); m12=s1[4]-'0'; c1=s1[5]; } if (s2[1]==':') { h2=s2[0]-'0'; m21=(s2[2]-'0'); m22=s2[3]-'0'; c2=s2[4]; } else { h2=(s2[0]-'0')*10+(s2[1]-'0'); m21=(s2[3]-'0'); m22=s2[4]-'0'; c2=s2[5]; } int cnt=0; if (c1!=c2) cnt++; cnt+=calc(h1,h2,12); cnt+=calc(m11,m21,6); cnt+=calc(m12,m22,10); printf("Going from %s to %s requires %d %s\n",s1,s2,cnt,(cnt==1)?"push.":"pushes."); } return 0; }參考程式
【練習5】HDU 3248 Strange Clock (http://acm.hdu.edu.cn/showproblem.php?pid=3248)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { int n,m; while (scanf("%d",&n) && n!=-1) { n = (n+270)%360; m = n / 30; m=12-m; if (n%30==0) printf("Exactly %d o'clock\n",m%12); else printf("Between %d o'clock and %d o'clock\n",(12+m-1)%12,m%12); } return 0; }參考程式