题目链接:
题目大意:
在某个工厂中有一些任务对(pi,qi),其中所有的p都必须在q之前完成,还有就是pi和qi完成时间上之间必须相差d[i],现在要你求出字典需最小的一种任务排列。
思路:
二进制枚举所有组合情况,结合pi与qi之间必须相差d[i],删除一些情况,并用map记录下已经算过的组合情况。
代码:
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
#define maxn 100
int d[maxn];
int n;
int p[maxn];
bool flag;
map<int,bool> mp;
void dfs(int k,int s){
if(k==n+1){
flag = true;
return;
}
for(int i=n+1;i<=2*n;i++){
if(i-d[k]>0 && p[i]==-1 && p[i-d[k]]==-1){
int ss = s| (1<<i);
ss = ss| (1<<(i-d[k]));
if(!mp[ss]){
mp[ss] = true;
p[i] = k;
p[i-d[k]] = k;
//printf("@%d %d %d\n",i,i-d[k],k);
dfs(k+1,ss);
if(flag) return;
p[i] = -1;
p[i-d[k]] = -1;
}
}
}
}
int main(){
while(scanf("%d",&n) && n){
for(int i=1;i<=n;i++) scanf("%d",&d[i]);
for(int i=1;i<=2*n;i++) p[i] = -1;
mp.clear();
flag = false;
dfs(1,0);
if(!flag) printf("no solution\n");
else{
for(int i=1;i<=2*n;i++){
printf(" %c%d",i<=n?'p':'q',p[i]);
}
printf("\n");
}
}
return 0;
}