赤裸裸的狀鴨TSP
就是在設計狀態的時候糾結了一下,到底鴨個數還是種類數?
好吧,目(mú)標意識又沒(mēi)有啦
目標在哪裏捏?收集全部種類的寶可夢!
所以這麼想的話世界突然就明亮了:
不用一頓亂check,只用枚舉一下每種寶可夢的每個寶可夢的位置就行了!
第二維如果表示種數的話,方程列不出來,因爲不知道抓的上一種在哪個位置,無法計算這次抓走的距離
然鵝,從(0,0)開始
寫完了才發現!!!!!
所以怎麼處理!!!!
枚舉第一個抓的和最後一個抓的,取min{dis((0,0)->first)+dp[E][last]+dis(last->(0,0))}
然鵝犯傻了的我當時竟然想歪了??
把(0,0)當第一種寶可夢。。。
然後就不知到怎麼的調了半天
//B2
#include <bits/stdc++.h>
using namespace std;
const int INF=1e9;
int dp[1<<16][22],d[22],n,mind=INF;
int nkind,kind[24];
vector<int>ve[20];
map<string,int>mp;
inline bool check(int i,int j,int k) {
if(!(i&d[kind[j]]))return 0;//這種沒有走過
if(i&d[kind[k]])return 0;//要抓的那個的屬性種已經去過
return 1;
}
struct node{
int x,y;
}pos[24];
int dis(int u,int v){
return abs(pos[u].x-pos[v].x)+abs(pos[u].y-pos[v].y);
}
int main() {
cin>>n;
n++;
string s;
nkind=1;
ve[1].push_back(1);
kind[1]=1;
mp["0"]=1;
for(int i=2;i<=n;i++){
cin>>pos[i].x>>pos[i].y>>s;
if(!mp[s])nkind++,mp[s]=nkind;
kind[i]=mp[s];
ve[kind[i]].push_back(i);
}
//最終狀態,第1到n位全都爲1
d[1]=1;
int E=(1<<nkind)-1;
//i=2!!!!
for(int i=2; i<=nkind; i++)d[i]=(d[i-1]<<1);//從1到n,位數爲i的二進制值 1 10 100 1000 10000,後面取用
for(int i=0; i<=E; i++)
for(int j=1; j<=n; j++)dp[i][j]=INF;//初始化狀態數組
dp[1][1]=0;
for(int i=1; i<=E; i++)
for(int j=1; j<=n; j++)//枚舉最後到的點
for(int k=1; k<=n; k++) {//枚舉將要到的點
if(check(i,j,k)) {//可以走,
for(int v=0;v<ve[kind[j]].size();v++){
dp[i + d[kind[k]]][k] =
min(dp[i + d[kind[k]]][k],
dp[i][ve[kind[j]][v]] +dis(ve[kind[j]][v], k));
}
}
}
for(int i=2;i<=nkind;i++){
for(int v=0;v<ve[i].size();v++)
mind = min(mind, dp[E][ve[i][v]] + dis(ve[i][v], 1))
}
cout<<mind;
return 0;
}