ICPC North Central NA Contest 2017 B - Pokemon Go Go

DOOOR

赤裸裸的狀鴨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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章