https://vjudge.net/problem/UVA-690
一台计算机有5个工作单元
一个任务有n个部分,每个部分都要使用一个工作单元
一个工作单元只能同时执行一个任务的一部分
现在有10个相同的任务需要执行
问最少用时
二进制记录每个工作单元当前的使用情况
枚举这个任务进行到哪个部分时,下一个任务开始
剪枝:
1、预处理pos[i] 表示 这个任务进行到哪个部分时,下一个任务可以开始
枚举的时候,只枚举这些部分
2、假设当前是第i个任务,前i-1的任务用时为k
第i个任务进行到第j个部分时,第i+1 个任务开始
若k+j+(10-i+1)* min(pos[])>=ans return
即之后的任务都用最早时间都>=当前答案,剪掉
#include<cstdio> #include<cstring> #include<algorithm>using namespace std;int n,bin[21];int cnt,pos[21],state[5];char s[21];int ans;bool judge(int v[5],int len) {for(int i=0;i<5;i++)if(state[i]&(v[i]>>len)) return false;return true; }void dfs(int task,int len,int window[5]) {if(task==10) {ans=min(ans,len);return;}int tmp[5];for(int i=1;i<=cnt;i++){if(!judge(window,pos[i])) continue;if(len+pos[i]+(10-task)*pos[0]>=ans) return;memcpy(tmp,window,sizeof(tmp));for(int j=0;j<5;j++) tmp[j]=(tmp[j]>>pos[i])|state[j];dfs(task+1,len+pos[i],tmp);} }int main() {bin[0]=1;for(int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;while(1){scanf("%d",&n);if(!n) return 0;for(int i=0;i<5;i++){scanf("%s",s); state[i]=0;for(int j=0;j<n;j++)if(s[j]=='X') state[i]|=bin[j];}cnt=0;for(int i=1;i<=n;i++) if(judge(state,i)) pos[++cnt]=i;ans=n*10;dfs(1,n,state);printf("%d\n",ans);} }