直接最多有6中化学药物。那么每种最多为10,且要表示改位存在要加1,采用十二进制,最大值在3000000左右,又可用状态比较少,使用记忆花搜索。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
#include <deque>
using namespace std;
const int maxk = 3501000;
int d[maxk],f[7][7],mi[10],t[7][7],n;
bool vis[maxk];
int sub(int& num,int i){
num=num-mi[i];
}
int digit(int num,int i){
return (num/mi[i])%12;
}
int dp(int j,int num){
if(vis[j]) return d[j];
vis[j] = true;
if(num==1){
return d[j] = 0;
}
d[j] = 1e9;
for(int k=0;k<n;k++)
for(int g=0;g<n;g++){
int d1 = digit(j,k);
int d2 = digit(j,g);
int num1 = j;
if((k!=g&&d1>1&&d2>1)||(k==g&&d1>=3)){
sub(num1,k);
sub(num1,g);
num1=num1+mi[t[k][g]-1];
d[j]=min(d[j],dp(num1,num-1)+f[k][g]);
}
}
return d[j];
}
int main()
{
mi[0] = 1;
for(int i=1;i<=7;i++) mi[i]=mi[i-1]*12;
int T;
scanf("%d",&T);
char str[100];
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++){
scanf("%d %d",&t[i][j],&f[i][j]);
}
memset(vis,false,sizeof(vis));
int cnt[11] = {0};
int k,x;
scanf("%d",&k);
for(int i=1;i<=k;i++){
scanf("%d",&x);
cnt[x]++;
}
int sum = 0;
for(int i=n;i>=1;i--){
sum=sum*12+cnt[i]+1;
}
scanf("%s",str);
printf("%d\n",dp(sum,k));
}
return 0;
}