質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.36%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

3回答

437閲覧

値段の組み合わせによる最小値問題が正しく求まらない

grape_ll

総合スコア83

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2020/08/23 11:53

下記のリンクの問題を解いていたのですが,15個あるケースの内3つがWAで不正解になってしまいます.数字の大きさ的には問題ないと思うのですが場合分けのところなどで間違っている個所がありましたら教えていただきたいです.
また,自分のやり方では全部の組み合わせを試して最小値を求めているのですが,もう少しうまいやり方がありそうな雰囲気がある問題だと思うので,なにか方法があれば教えていただきたいです.よろしくお願いします.

問題

C

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4#include<math.h> 5 6 7int main(void){ 8 9 int Aprice,Bprice,Cprice; 10 int numA,numB; 11 12 scanf("%d %d %d %d %d",&Aprice,&Bprice,&Cprice,&numA,&numB); 13 14 long ans=500000000; 15 int numMAX=0; 16 if(numA>numB) numMAX=numA; 17 else numMAX=numB; 18 19 long price; 20 21 for(int i=0;i<=numMAX;i++){ 22 if(numA>=i && numB>=i) price=Aprice*(numA-i)+Bprice*(numB-i)+Cprice*2*i; 23 else if(numA>=i && numB<i) price=Aprice*(numA-i)+Cprice*2*i; 24 else if(numA<i && numB>=i) price=Bprice*(numB-i)+Cprice*2*i; 25 26 if(price<ans) ans=price; 27 } 28 29 printf("%ld\n",ans); 30 31 return 0; 32} 33

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

A,B,Cがすべて5000で、X,Yがともに10^5である場合、
10^9が最小値となり、ansの5*10^8を更新できません。

ansの初期値を、intが取りうる最大値にしておくのが一番安全です。

投稿2020/08/23 15:17

swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/08/24 11:01

理論上の最大値の見積もりが杜撰でした.気を付けます.ご指摘ありがとうございます.
guest

0

ベストアンサー

正しい解にならないのはansの初期値が理論上の最大値よりも小さいからでしょう。

全探索以外の解き方としては、例えば

C

1price=Bprice*(numB-i)+Cprice*2*i;

この式を見ると、priceは傾きがCprice * 2 - Bpriceのiの一次式になっています。なので、価格が最小になるのはiが最小の場合か最大の場合かのどちらかで、それは傾きの正負を見れば計算せずともわかります。
同様のことを3つの式についても考えれば、3つともiの一次式になってるのでこれを解くか、条件を満たす最大最小のiを調べるかをすることで、すべてのiを調べずに最小値が出せます。

投稿2020/08/23 12:49

yudedako67

総合スコア2047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/08/24 11:06

理論上の最大値を正しく初期化しましたら無事通りました.ご指摘ありがとうございます. 確かにiに関する一次関数とみて,傾きを気にしてあげると計算量の削減ができますね.プログラミングにおいてそのような考え方で解いたことがなかったので大変参考になりました.ありがとうございます.
guest

0

なぜそのコードで通らないかは分かりませんが、もう少しうまい場合分けができそうです。
A+B<=2Cの時、ABのピザを買うメリットはないので、答えはA*X+B*Yです。
A+B>2Cの時、ABのピザを買えば買うほど安くなるので、AがXを、BがYを超えない最大の2 * min(X,Y)枚買うとします。
さらに、XとY大きい方のピザをmax(X,Y)-min(X,Y)枚を買う必要があります。
仮に、Xの方が大きかったとしましょう。
Aを揃えるのに、A>2CならBは無駄になってもCを2*(max(X,Y)-min(X,Y))枚買った方が安いです。
もしA<2CならAを直接max(X,Y)-min(X,Y)枚買った方が安いです。

--追記--
なぜ質問のコードでACとならないかについて追記します。
片方のピザを余らせた場合に値引きをしてしまっているからです。
もしA!=Bなら、numA-iまたはnumB-iが負になることがあります。
つまり、このコードだと余ったピザ分だけ値引きしていることになってしまいます。

投稿2020/08/23 12:31

編集2020/08/23 13:17
auto-blue

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/08/24 11:13

通らない理由は理論上の最大値がうまく初期化できていないからでした. 場合分けは確かにおっしゃるやり方でもできそうで,実際,自分も最初はそのようなアプローチでやってみようと考えたのですが,関数をmax関数やmina関数を作ったり分岐が少し複雑になったりするよりかは,単純な場合分けの方が自分の頭では混乱しなくて済むのではないかと考えてこの方法をとりました. また,追記についてですが,このコードになる前にその値引きをしていることコードをかいてしまっていたので,改良してこのコードでは場合分けによって値引きがされないようになっていると思います. ですがこれからのコードを書いていくうえで注意すべき点の確認は出来ましたの.ご回答ありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問