思路:
1.状压dp+记忆化搜索
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int INF=0x3f3f3f3f; int dp[(1<<20)+5]; int a[25]; int n; int dfs(int sum,int sta){ if(dp[sta]!=INF)return dp[sta]; for(int i=0;i<n;i++){ if(sta&(1<<i)){ int temp=sta-(1<<i); int tsum=sum-a[i]; int l=(i-1+n)%n; int r=(i+1)%n; if(sta&(1<<l))temp-=1<<l,tsum-=a[l]; if(sta&(1<<r))temp-=1<<r,tsum-=a[r]; dp[sta]=min(dp[sta],dfs(tsum,temp)+tsum); } } return dp[sta]; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int sum=0; mem(dp,INF); dp[0]=0; cin>>n; for(int i=0;i<n;i++)cin>>a[i],sum+=a[i]; cout<<dfs(sum,(1<<n)-1)<<endl; return 0; }
2.dfs+剪枝
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=30; const int INF=0x7f7f7f7f; int a[N],sum[N]; bool vis[N]; int ans=INF,n; void dfs(int res,int t){ if(t>=ans)return ;//剪枝 if(res==0){ ans=min(ans,t); } for(int i=1;i<=n;i++){ if(!vis[i]){ int l=i-1; int r=i+1; if(l==0)l=n; if(r==n+1)r=1; if(vis[l])l=25; if(vis[r])r=25; vis[l]=vis[i]=vis[r]=true; dfs(res-a[l]-a[i]-a[r],t+res-a[l]-a[i]-a[r]); vis[l]=vis[i]=vis[r]=false; } } } int main(){ ios::sync_with_stdio(false); cin.tie(0); int sum=0; cin>>n; for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i]; dfs(sum,0); cout<<ans<<endl; return 0; }