AOJ1204 Pipeline Scheduling

問題リンク Pipeline Scheduling

  • 概要

ユニットが5個あり、1つのタスクを処理するための手順表が与えられる。表の長さはNである。
処理を行うクロックに衝突が生じないように10個のタスクを処理するための最小クロック数を答えよ。
N < 20

  • 解法

深さ優先探索+枝刈りで解きました。
タスクkを処理し始めることができる最初のクロックをhとします。また、これまでのタスク処理で使用した最大のクロックをmaxとします。
このときタスクは、h〜max+1クロックからはじめるのが候補となります。これらのクロックを処理開始先頭クロックとしたとき、衝突が生じないならばクロック表を埋めて再帰します。
maxがこれまでの解を超えた場合、もしくは、h+Nが解以上となるとき、解の更新が絶対に見込めないので刈ります。

  • ソース
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

//Pipeline Scheduling
public class AOJ1204 {

	List<Integer>[] e;
	boolean[][] t;
	int res, n;
	
	void dfs(int k, int h, int max){
		if(k==10){
			res = Math.min(res, max); return;
		}
		if(res<=max||res<=h+n)return;
		for(int i=h;i<=max;i++){
			boolean ok = true;
			for(int y=0;y<5;y++){
				if(!ok)break;
				for(int x:e[y]){
					if(t[y][i+x]){
						ok = false; break;
					}
				}
			}
			if(ok){
				int m = 0;
				for(int y=0;y<5;y++){
					for(int x:e[y]){
						t[y][i+x] = true;
						m = Math.max(m, i+x);
					}
				}
				dfs(k+1, i+1, m);
				for(int y=0;y<5;y++){
					for(int x:e[y]){
						t[y][i+x] = false;
					}
				}
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			n = sc.nextInt();
			if(n==0)break;
			e = new List[5];
			for(int i=0;i<5;i++)e[i]=new ArrayList<Integer>();
			t = new boolean[5][210];
			for(int i=0;i<5;i++){
				char[] s = sc.next().toCharArray();
				for(int j=0;j<n;j++)if(s[j]=='X'){
					t[i][j] = true; e[i].add(j);
				}
			}
			res = 1<<29;
			dfs(1, 0, n);
			System.out.println(res+1);
		}
	}
	
	public static void main(String[] args) {
		new AOJ1204().run();
	}
}