問題はこちら
No.161 制限ジャンケン - yukicoder
相手が出す手がわかっているので順序は関係ない
可能な限り勝てるような手を出せば良い
#define min(a,b)(a<b?a:b) int main(){ int a[3]={},b[3]={},s,i,t; scanf("%d%d%d\n",a,a+1,a+2); for(;t=~getchar();){ if(~t=='G')b[0]++; else if(~t=='C')b[1]++; else if(~t=='P')b[2]++; } s=0; //勝てる手を出す for(i=0;i<3;i++){ t=min(a[i],b[(i+1)%3]); a[i]-=t; b[(i+1)%3]-=t; s+=t*3; } //残りは引き分け for(i=0;i<3;i++)s+=min(a[i],b[i]); printf("%d",s); return 0; }
まずは読み込み部分
'G'が71、'C'が67、'P'が80なのでgetchar()/7で10,9,11にすることができる。このとき改行は1でEOFは0
勝てる手をだす処理も、読み込みが終わってからではなく随時実行することにすればループを1つ減らせる
(引き分け処理は勝てる手を全て出し終わった後でなければならない)
ということでこうまとめられる
for(scanf("%d%d%d",a+1,a,a+2);t=getchar()/7;)t-1?a[i=(t+1)%3]?a[i]--,s+=3:b[t%3]++:0; //この部分だけならt-1?a[i=(t+1)%3]--?s+=3:b[t%3]++:0;でもいいが //引き分け処理が面倒になるのでaには0未満の値が入らないようにしておく
最後にループ圧縮をして
for(scanf("%d%d%d",a+1,a,a+2);t=getchar()/7;)t-1?a[i=(t+1)%3]?a[i]--,s+=3:b[t%3]++:0;for(i=0;i<3;i++)s+=a[i]<b[i]?a[i]:b[i]; //iの初期化の都合でt-1の分岐をやめてみる(こうすると最後に改行を読み込んだ時にi=2が代入される) //b[-8]にアクセスしているが偶然うまくいく for(scanf("%d%d%d",a+1,a,a+2);(t=getchar()/7)?a[i=(t+1)%3]&&t-1?a[i]--,s+=3:++b[t-9]:(s+=a[i]<b[i]?a[i]:b[i],i--);); for(scanf("%d%d%d",a+1,a,a+2);!(t=getchar()/7)?s+=a[i]<b[i]?a[i]:b[i],i--:a[i=(t+1)%3]&&t-1?a[i]--,s+=3:++b[t-9];);
ということでまとめると
a[9],b[9],s,i; main(t){ for(scanf("%d%d%d",a+1,a,a+2);!(t=getchar()/7)?s+=a[i]<b[i]?a[i]:b[i],i--:a[i=(t+1)%3]&&t-1?a[i]--,s+=3:++b[t-9];); s!=printf("%d",s); }
156B
2016/05/18追記
&&を*に書き換えられる箇所があったので1B短縮
a[9],b[9],s,i; main(t){ for(scanf("%d%d%d",a+1,a,a+2);!(t=getchar()/7)?s+=a[i]<b[i]?a[i]:b[i],i--:a[i=(t+1)%3]*~-t?a[i]--,s+=3:++b[t-9];); s=!printf("%d",s); }
155B
16/06/06追記
fminの存在を忘れていた
a[9],b[9],s,i; main(t){ for(scanf("%d%d%d",a+1,a,a+2);!(t=getchar()/7)?s+=fmin(a[i],b[i]),i--:a[i=(t+1)%3]*~-t?a[i]--,s+=3:++b[t-9];); s=!printf("%d",s); }
151B