こちらの問題を解いていました
お札n枚でY円を作ることが可能か、可能な場合は一つだけその組を出力せよ、という問題です
これは単純な全探索で解くことができ、自力で解くことができました
しかし初めは再帰関数を使おうと思って解こうと思ったのですが、それではうまくいきませんでした
色々試してごちゃごちゃですが、コードは以下の通りでした
なおコメントアウトの部分はメモ化を行おうとしたけどメモリが足りなくなったのでやめた跡です(多分vectorを使えばいけると思いますが、今回はそこまで制約の厳しい問題ではないので)
c++
1#include<bits/stdc++.h> 2using namespace std; 3 4//long long dp[2000][2000][2000]; 5 6bool solve(long long x,long long y,long long z,long long n,long long Y){ 7/* if(dp[x][y][z]!=-1){ 8 return dp[x][y][z]; 9 }*/ 10 int flag=0; 11 long long sum=0; 12 long long res; 13 long long *ans_x=0,*ans_y=0,*ans_z=0; 14 sum = x*1000+y*5000+z*10000; 15 //cout<<sum<<endl; 16 if((x+y+z)==n){ 17 if(sum==Y){ 18 //cout<<z<<" "<<y<<" "<<x<<endl;//複数出力されてしまう 19 flag=1; 20 *ans_x=x; 21 *ans_y=y; 22 *ans_z=z; 23 return true; 24 } 25 }else if((x+y+z)<n){ 26// return dp[x][y][z]=solve(x+1,y,z,n); 27// return dp[x][y][z]=solve(x,y+1,z,n); 28// return dp[x][y][z]=solve(x,y,z+1,n); 29 solve(x+1,y,z,n,Y); 30 solve(x,y+1,z,n,Y); 31 solve(x,y,z+1,n,Y); 32 }else{ 33 //return false; 34 } 35} 36 37int main(){ 38// memset(dp,-1,sizeof(dp)); 39 long long n,Y; 40 cin>>n>>Y; 41 long long x=0,y=0,z=0; 42 long long *ans_x=0,*ans_y=0,*ans_z=0; 43 long long check=n*10000; 44 if(check<Y){ 45 cout<<"-1 -1 -1"<<endl; 46 }else{ 47 if(solve(x,y,z,n,Y)){ 48 //cout<<"aaa"<<endl; 49 cout<<*ans_z<<" "<<*ans_y<<" "<<*ans_x<<endl; 50 return 0; 51 }else{ 52 cout<<"-1 -1 -1"<<endl; 53 } 54 } 55 return 0; 56} 57
再帰関数では見ての通り、1000円、5000円、10000円札のどれかを1つ増やしていって、合計枚数がnと一致すれば出力といった風にしたいです
しかし、再帰関数では並列処理が行われてしまうため、プログラムが試した全ての組みが出力されてしまいます。単純にフラグを建てる方法などでは無意味でした
そのためポインタを使って、最初に見つけたお札の組みをmain関数に送ろうと考えたのですが、現状ではx+y+z>nのとき(solve関数内のelseの部分です)も試されてしまっており、ここを何とかしなければならないのですが、どうすれば良いのか分かりませんでした
それにより挙動が意味不明なため、ポインタの処理はちゃんと書けていません
どなたか正しい書き方をご教授いただけないでしょうか
よろしくお願いします
回答3件
あなたの回答
tips
プレビュー