題意:一個女孩整理箱子,箱子的位置不可以改變,她一次可以拿兩個或者是一個行李,女孩移動時間花費是她移動距離的平方。
做法:狀態壓縮DP 還是不熟啊,要瞟一眼打大神部落格才行。
/*******劃分狀態,這種題目總是以為要用DFS做,可是也不知道怎麼DFS啊。。。所以,觀察,發現只有24件物品,拿每一個物品時,你可以拿兩個,可是拿第二個物品時,受前面狀態的幹擾,有且僅有這樣一個幹擾。所以狀態壓縮吧。其實這個狀態可以無視拿東西的順序。其實這個狀態可以無視拿東西的順序,所以可以認為的假定拿完i後才能拿i+1,因為這樣一來i+1物品拿第二件物品的選擇權並不會有損害,還是可以更新狀態。每計算拿一個物品時,可以新增出兩個狀態,拿一個,和兩個,新增的狀態是不可以當原來的狀態考慮的。。。by CF某大神***/#include<cstdio>#include <cstring>#include <iostream>using namespace std;const int LMT=1<<24;int dp[LMT],pre[LMT],gra[26][26],x[26],y[26],ans[60];int main(void){ int n,x0,y0; cin>>x0>>y0;cin>>n; for(int i=0;i<n;i++)cin>>x[i]>>y[i]; x[n]=x0;y[n]=y0; for(int i=0;i<=n;i++) for(int j=i+1;j<=n;j++) gra[i][j]=gra[j][i]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); memset(dp,-1,sizeof(dp));dp[0]=0; for(int i=0;i<1<<n;i++) if(dp[i]!=-1) { for(int j=0;j<n;j++) if(!((1<<j)&i)) { int t=i|(1<<j),tem=dp[i]+2*gra[j][n]; if(dp[t]==-1||dp[t]>tem) { dp[t]=tem; pre[t]=i; } for(int k=0;k<n;k++)//只能拿在這個狀態下,沒有拿過的 if(!(t&(1<<k))) { int t2=t|(1<<k),tem=dp[i]+gra[n][j]+gra[j][k]+gra[k][n]; if(dp[t2]==-1||dp[t2]>tem) { dp[t2]=tem; pre[t2]=i; } } break; } } int x=(1<<n)-1,pr,tem,a,b,cnt=0; cout<<dp[x]<<endl; while(x) { pr=pre[x];tem=pr^x; a=b=0; for(int i=0;i<n;i++) if((1<<i)&tem) { b=a; a=i+1; } ans[cnt++]=0; ans[cnt++]=a; if(b)ans[cnt++]=b; x=pr; } ans[cnt++]=0; for(int i=cnt-1;i>=0;i--) printf("%d ",ans[i]); printf("\n"); return 0;}