読者です 読者をやめる 読者になる 読者になる

AOJ 2250: Operator

たまに見る二分探索トラップ。
嘘解法ごめんなさい……。

#include<stdio.h>
#include<algorithm>
using namespace std;
int c[1100];
int d[1100];
int e[1100];
int fin[1100];
int next[1100];
int a,b;
int can(int M){
	for(int i=0;i<M;i++)fin[i]=0;
	for(int i=0;i<a;i++)next[i]=0;
	int last=0;
	int rem=a;
	for(int i=0;i<b;i++){
		for(int j=0;j<M;j++){
			if(fin[j]<=i){
				for(int k=0;k<a;k++){
					if(~next[k]&&next[k]<=i){
						next[k]=-1;
						fin[j]=i+c[k];
						last=max(last,fin[j]);
						rem--;
						break;
					}
				}
			}
		}
		for(int j=0;j<a;j++){
			if(~next[j]&&i==next[j]+d[j]){
				next[j]=next[j]+d[j]+e[j];
			}
		}
		if(!rem)break;
	}
	for(int i=0;i<a;i++)if(~next[i])last=9999999;
	if(last<=b)return 1;
	return 0;
}
int main(){
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)scanf("%d%d%d",c+i,d+i,e+i);
		int left=0;
		int right=1001;
		while(left+1<right){
			int M=(left+right)/2;
			if(can(M)){
				right=M;
			}else left=M;
		}
		int tr=right;
		for(int i=1;i<=10&&tr-i>0;i++){
			if(can(tr-i))right=tr-i;
		}
		printf("%d\n",right);
	}
}