UVA 10604(进制式dp)

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

你可能感兴趣的:(UVA 10604(进制式dp))