Hang Dian oj 1006 Tick andTick個人的な問題の解決策

Hang Dian oj 1006 Tick andTick個人的な問題の解決策

まず、公式サイトに元の質問を掲載しましたが、
ハングディアンオリジナルタイトル
最初はこの質問を見て、また水に関する質問だと思いましたが、よく見てみると、もっと数学のテストだと気づき、本当に長い間苦労しました。これが私の考えのいくつかです:

アイデア1:暴力シミュレーション方法

おそらくほとんどの人は秒を使って時計をシミュレートし、秒数に応じて時針と分針の位置を決定し、時間を累積します。ここでは、1秒、0.1秒、0.01秒、さらには0.001秒を単位時間シミュレーションとして使用できますが、実際には2つの大きな欠点:
1。単位時間が短く、シミュレーションの数が多い。
2.精度が十分でない場合は、小数点以下3桁を維持してください。
シミュレートするのに秒を使用していませんが、秒針が移動した度を使用してシミュレートしているため、時間と度の変換を節約できます。
知っておく必要があるのは、秒針の速度= 60×分針の速度= 720×時針の速度
です。これが私が書いたコードです(最初のアイデアとして提出され、ojで失敗しました)。

#include<bits/stdc++.h>//这个头文件也称万能头,包括c和c++的很多头文件
using namespace std;
int main()
{
    
    
    int n;
    double a=0,t=0,miao,fen,shi;
    cin>>n;
    while(n<=120&&n>=0)
    {
    
    
        //模拟时钟
        while(shi<360)
        {
    
    
            t+=0.45;//t是计算总时间,以0.45°为单位累加
            miao=t-(int)t/360*360;//这里因为t为double型,用不了%,所以自己写了一个类似与%的东西。
            fen=t/60-(int)t/60/360*360;
            shi=t/720;
            if(abs(miao-fen)>=n&&miao-fen+360>=n&&fen+360-miao>=n)//这里的判断略显繁琐,其实可以用define宏来简化代码。
               if(abs(miao-shi)>=n&&miao-shi+360>=n&&shi+360-miao>=n)
                  if(abs(fen-shi)>=n&&fen-shi+360>=n&&shi+360-fen>=n)
                     a+=0.45;//a用来统计开心时间
        }
        printf("%.3lf\n",a/t*100);//c++的小数点控制不大会用,方便起见用了c的printf函数
        cin>>n;
        a=t=shi=0;//这里需要重置数据
    }
    cin.get();
    cin.get();//这里用两个cin.get();来暂停界面,保留窗口,不影响oj的判断
}

実際には、処理プロセスの詳細は次のように多くあります。
たとえば、abs(miao-fen)> = nのように3つのifが記述され、miaoとfenの程度の違いを判断します。ここでは、fenの程度が可能であるため、absが使用されます。 miao以上(開始位置に対して)。また、次の(miao-fen + 360)> = nおよびfen-miao + 360は、別の角度を計算するために使用されます。

その後、この0.45を何度かデバッグしました。最初は0.01を使用しました。実行後、実行時間が長すぎることがわかったので、大きい値に変更して1にしました。テストサンプルは正しかったのですが、提出時に提出しました。間違っています(十分な精度がありません)。
提出された写真を貼り付け
ここに写真の説明を挿入ここに写真の説明を挿入
ます。ここに間違った答えが表示され、実行時間も短くありません。
だから私は時間を正確さと交換しようとした。
結果は図のようになります。
ここに写真の説明を挿入
ここに写真の説明を挿入
次に、0.5に増やしてみます:減らします
ここに写真の説明を挿入
(心が疲れます)、0.45:
ここに写真の説明を挿入
ojが拒否する適切なアルゴリズムがないことがわかります!
そこでBaiduを始めて、他の多くのブロガーが方程式を解く形式を使用していることに気づきましたが、全員がコードを投稿していました。理解できなかったか、読むのに長すぎました。あきらめたかったのですが、後で考えました。そうしないと絶対に起こらないので、もう一度やり直したほうがいいです。
今日一日中過ごした後、私はついにノックアウトしました。それがアイデア2です。

アイデア2:方程式を解き、条件を満たす2つの間の間隔を計算し、最後に交点を取り、間隔をマージします。

チャット:

私の苦労全体について話させてください(ブロガーの個人的なナンセンスである、見たくない場合はスキップできます):
最初に、数学の問題を使用するというアイデアについて考えました、つまり、最初に分針と時針にnクリップを生成させます角度を付け、この時点で時間を計算し、これに基づいて秒針の位置を決定します。これが途中で諦めたコードです。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    int n,q=0;
    double miao=0,fen,shi,t1,t2,t3,t4,ans=0;
    cin>>n;
    while(n<=120&&n>=0)
    {
    
    
        //解多次方程
        while(720/11*(n+q*360)<259200)//用度数来解方程
        {
    
    
           t1=720/11*(n+q*360);q++;//解出分针与时针满足条件时的时间
           t2=720/11*(q*360-n);//t1,t2用来确定分针和时针开心的边界,t3,t4用来确定秒针分别与时针和分针的开心边界
           //用for循环寻找在t1-t2该区间的miao的范围
           t3=t4=0;
           
 
           for(int i=0;t3<259200;i++)
           {
    
    
               t3=(n+(i*360))*720/719;
               if(t1<t3&&t3<t2)break;
           }
           for(int i=0;t4<259200;i++)
           {
    
    
               t4=(360*(i+1)-n)*720/719;
           }      
        }
        
    }
    cin.get();
    cin.get();
}

しかし、後で私はそれが間違っていることに気付きました。T3とt4は前にあり、後ろには何がありますか?T3とt4は公開部分に移動する必要があり、最後のt3または最後のt4の時間などと重複する可能性があり
ます。すべての問題を解決するために大量のデータを保存できる

正题:

実際、この質問を振り返ると、彼が私たちに求めたのは、条件を満たすすべての時間間隔を計算し、それらを加算して、最後に合計時間の割合を計算することであることがわかります。
1日24時間の最初の12時間と最後の12時間だからです。時間の状況は同じなので、合計時間として12時間を使用します。
まず、この質問の一般的なフレームワークは、条件を直接満たす間隔を計算することです(3つの条件すべてを一度に満たすことはできません)。計算)
つまり、時針と秒針の間隔、時針と分針の間隔、分針と時針の間隔で、最後に交差点を取得します。
最初にコードを貼り付けてから、次のように説明します。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
    int n,s1=0,s2=0,s3=0,s4=0;
    double ms[2000],fs[30],fm[2000],h1[2000],ans=0;
    cin>>n;
    while(n<=120&&n>=0)
    {
    
    
        for(int i=0;(n+360*i)*720.0/719<259200;i++)
        {
    
    
            ms[s1++]=(n+360*i)*720.0/719;
            ms[s1++]=((i+1)*360-n)*720.0/719;
        }

        for(int i=0;(n+360*i)*720.0/11<259200;i++)
        {
    
    
            fs[s2++]=(n+360*i)*720.0/11;
            fs[s2++]=((i+1)*360-n)*720.0/11;
        }

        for(int i=0;(n+360*i)*60.0/59<259200;i++)
        {
    
    
            fm[s3++]=(n+360*i)*60.0/59;
            fm[s3++]=((i+1)*360-n)*60.0/59;
        }
        //合并fs和fm,并入h1之中
        for(int i=0;i<s2;i+=2)
          for(int j=0;j<s3&&fm[j]<fs[i+1];j+=2)
          {
    
    
              if(fm[j+1]>fs[i])
              {
    
    
                  h1[s4++]=max(fm[j],fs[i]);
                  h1[s4++]=min(fm[j+1],fs[i+1]);
              }
          }
        //合并h1和ms,并入fm
        s3=0;
        for(int i=0;i<s4;i+=2)
        for(int j=0;j<s1&&ms[j]<h1[i+1];j+=2)
        {
    
    
            if(ms[j+1]>h1[i])
            {
    
    
                fm[s3++]=max(ms[j],h1[i]);
                fm[s3++]=min(ms[j+1],h1[i+1]);
            }
        }
        for(int i=0;i<s3;i+=2)ans+=fm[i+1]-fm[i];
        printf("%.3f\n",ans/259200*100);
        s1=s2=s3=s4=ans=0;
        cin>>n;
    }
    cin.get();
    cin.get();
}

46msは大丈夫です
1.1。
intタイプ:
nは入力データを格納するために使用されます
s1はms配列の要素数を格納するために使用されます(1440、保険目的で2000を使用)
s2はfs配列内の要素数を格納します(
24、30を使用)s3はfm配列を格納します(推定1440、2000を使用)
s4の要素数は、h1配列の要素数(推定1440、2000を使用)を格納します。
2.2。
ダブルアレイ:
msアレイは、秒針と時針が条件を満たす間隔(msは秒の省略形)
など
を格納します。h1アレイは、最初のマージの間隔を格納するために使用されます(2 x 2マージは2回、元々は2つあるはずです)。配列はマージ間隔を格納するために使用されますが、最初にfsとfmをマージしたため、fm配列は2回目のマージでは役に立たず、最後の間隔配列として空にすることができます。さらに、fs配列の値は非常に少ないため、最初にマージします。 fs配列は数倍少なくループすることができます)
doubleansは幸せな時間を保存するために使用されます。
3.(コア部分)
それを計算する方法は方程式を解く方法ですか?

実際には非常に単純です。例として、秒針と時針のn = 90°を取り上げます。ここでは、次数シーケンスの式を使用します。つまり、秒針の次数をxに設定すると、最初に条件が満たされます
。xx/ 720 = 90
の秒針が時針をもう1円超えた場合どうなりますか?
xx / 720 = 90 + 360
別の円はどうですか?
xx / 720 = 90 + 360×2

xx / 720 = 90 + 360×i
この場合、解はx =(90 + 360 ×i)×720/719。

実際に
は、時針と秒針という別の状況があります。
秒針が時針を超えて時針を追いかけると、最初に条件が満たされたとき:
x / 720 + 360-x = 90、
iサークルの後同じことが言えます:
x / 720 + 360×ix = 90
はx =(360×i-90)×720/719に解決されます。

次に、秒針と分針、分針と時針を同じように類推することができます。
最後に、2つずつ組み合わせて時間と時間を累積します。次の計算のために比率を出力した後、データをリセットすることを忘れないでください。

(追記:ブロガーをサポートするコメント、深夜12時30分、少し眠いです〜)

下書きを添付してください(ランダムなもの)
ここに写真の説明を挿入

おすすめ

転載: blog.csdn.net/qq_35598074/article/details/109232379