直接最多有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; }