https://vjudge.net/problem/UVA-690
有10个任务,5个管道,每个任务需要占用不同时间的管道,给出任务所占用管道的时间,求最短需要多少时间。
dfs+剪枝,当当前开销加上剩余任务的最有情况仍大于ans。
利用位运算模拟矩阵的情况,每次将无用的列往前移动。
之后判断需要往前移动多少能插入新的任务次序
#include <bits/stdc++.h>
using namespace std;
char d[1005];
int dp[5000];
int tag[100];
int n,maxs,mins,e;
bool run(int *s,int k)
{
for(int i=0;i<5;i++)
{
if((s[i]>>k)&tag[i]) return false;
}
return true;
}
void dfs(int *s,int d,int sum)
{
if(sum+dp[0]*(10-d)>mins) return ;
if(d==10)
{
if(sum<mins) mins=sum;
return;
}
for(int i=0;i<e;i++)
{
int p[5];
if(run(s,dp[i]))
{
for(int j=0;j<5;j++)
{
p[j]=(s[j]>>dp[i])|tag[j];
}
dfs(p,d+1,sum+dp[i]);
}
}
}
int main()
{
while(cin>>n&&n)
{
memset(dp,0,sizeof(dp));
memset(tag,0,sizeof(tag));
mins=20000;
for(int i=0;i<5;i++)
{
cin>>d;
for(int j=0;j<n;j++)
{
if(d[j]=='X')
{
tag[i]|=(1<<j);
}
}
//cout<<tag[i]<<endl;
}
e=0;
for(int i=0;i<=n;i++)
{
if(run(tag,i))
{
dp[e++]=i;
//cout<<i<<endl;
}
}
// for(int i=0;i<n;i++)cout<<tag[i]<<' ';cout<<endl;
dfs(tag,1,n);
cout<<mins<<endl;
}
}