第一行一个数n(3≤n≤16)
接下来n行每行n个数,第x行第y个数表示p[x][y](0≤p[x][y]≤100000)
一个数,表示最小代价
3 0 2 1 2 0 1 3 1 0
2
1->2重力加速
2->3反重力加速
代价0+1*2=2
(题解建议配合代码一起食用喵~)
不会这道题吗?让猫猫来帮帮你吧!
我们先看看怎么表示状态的喵~
这道题我定义了dp数组dp[i][j][k]喵!
既然是dp那肯定有状态转移公式的喵!
dp[i][j][k]肯定是由上一个状态转移(dp[ii][jj][kk])来的喵!
首先 i 中,j 的状态会消失。因为 j 是现在所在的空间站位置。所以ii就等于i - ( 1 << j )表示未包含 j 的状态。
因为其他任何空间站都有可能跳到 j 空间站,所以 jj 我们要从1到n进行遍历一遍。(注意jj一定要在ii的状态内,猫猫总不可能还没有到那里就可以从jj开始跳吧)
dp[i][j][0~3]=min(dp[i][j][0~3],dp[ii][jj][0~3]+m[jj][j]);//m[jj][j]表示从jj跳到j需要花的动能 //各个状态普通跳 dp[i][j][1]=min(dp[i][j][1],dp[ii][jj][0]);//重力加速 //这次跳跃不要钱啦! dp[i][j][2]=min(dp[i][j][2],dp[ii][jj][0]+m[k][j]*2);//反重力加速 //代价变成两倍,但有时候为了整体最优还是值得的喵! dp[i][j][3]=min(dp[i][j][3],dp[ii][jj][1]+m[k][j]*2);//已经重力加速过了,进行一次反重力加速 dp[i][j][3]=min(dp[i][j][3],dp[ii][jj][2]);//已经反重力加速过了,进行一次重力加速
思路是不是非常简单呢?
呈上代码喵!
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
int main() {
cin.tie(0)->sync_with_stdio(0);
ll n;cin >> n;
vector<vector<ll>> m(n,vector<ll>(n));
vector<vector<vector<ll>>> dp(1<<n,vector<vector<ll>>(n,vector<ll>(4,1e9)));
//等同于ll dp[1<<n][n][4]且每个元素都是1e9
//这个三维数组最好不要直接用int dp[][][]表示在主函数内,可能会内存溢出。
//如果很想用可以放在全局变量里
for(ll i=0;i<n;i++)
{
for(ll j=0;j<n;j++)
{
cin >> m[i][j];//初始化
}
}
for(ll i=0;i<n;i++) dp[1<<i][i][0]=0;//表示一开始就在某一个空间站的情况,耗费动能肯定是0呀
for(ll i=1;i<(1<<n);i++)//遍历所有状态
{
for(ll j=0;j<n;j++)//当前刚好处于j站点
{
if(!(i>>j&1)) continue;//如果j不在状态i中就跳过
for(int jj=0;jj<n;jj++)//上一个点jj
{
if(j==jj||!(i>>jj&1)) continue;//jj不在i中或者等于j就跳过
int ii=i-(1<<j);
for(int l=0;l<4;l++)
dp[i][j][l]=min(dp[i][j][l],dp[ii][jj][l]+m[jj][j]);//各状态普通跳
dp[i][j][1]=min(dp[i][j][1],dp[ii][jj][0]);//重力加速
dp[i][j][2]=min(dp[i][j][2],dp[ii][jj][0]+m[jj][j]*2);//反重力加速
dp[i][j][3]=min(dp[i][j][3],dp[ii][jj][1]+m[jj][j]*2);//已经重力加速过了
dp[i][j][3]=min(dp[i][j][3],dp[ii][jj][2]);//已经反重力加速过了
}
}
}
ll ans=1e9;
for(int i=0;i<n;i++)
{
ans=min(ans,dp[(1<<n)-1][i][3]);
}
cout << ans;
}
/*
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣤⡀⣀⣠⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣀⡀⢀⣴⣾⣷⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⣾⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⠿⠛⠛⠉⠉⠉⠉⠉⠉⠛⠻⠿⣿⣿⣿⣿⣿⣶⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⣿⡿⠿⠛⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣀⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⣰⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣠⣾⣿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣶⣄⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣻⣿⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢹⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⠁⠈⢢⡀⠀⠀⠀⢸⡇⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⡟⠒⢦⡀⠀⠀⠀
⠀⠀⣠⣤⣤⣼⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡇⠀⠀⠀⠉⢢⣄⠀⠀⢿⠊⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣷⡄⠀⢷⠀⠀⠀
⠀⢰⠇⠀⣰⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⡌⣹⠗⠦⣬⣇⠀⠉⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡀⢸⡄⠀⠀
⠀⡟⠀⣼⣯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣆⢹⡀⠀⠀⠀⠉⠁⠀⠀⢀⣀⡁⠀⠀⠉⠳⢴⡆⠀⠀⠀⠀⠀⠀⢹⣧⠈⡇⠀⠀
⠀⡇⠀⠀⢻⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣾⠻⠉⠛⠂⠀⠀⠀⠀⠀⠀⠻⠿⣿⣿⣿⣶⣦⡀⠛⣇⠀⠀⠀⠀⠀⣈⣿⠀⡇⠀⠀
⢸⡇⠀⠀⢠⣿⣷⣦⣀⡸⣷⣦⣶⡂⠉⠉⠉⢁⣤⣶⡶⠀⠀⠀⣀⣀⡴⠀⠀⠀⠀⠀⠀⠈⠉⠉⠁⠀⡟⢀⣴⣟⣰⣾⣿⣏⣠⠇⠀⠀
⠈⡇⠀⠀⢸⣿⠁⠉⣿⠛⠛⠃⡇⠀⠀⢠⣶⣿⡿⠛⠁⠀⠀⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⢿⠟⠿⢿⡏⠀⠘⣿⡀⠀⠀⠀
⠀⢷⣀⣀⣿⠇⠀⠀⢿⡇⠀⢀⢱⡀⠀⠛⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⠀⢸⠇⠀⠀⢹⣿⣄⠀⠀
⠀⠀⣉⣿⡏⠀⠀⠀⠀⠀⠀⢸⣇⣳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⣿⠃⠀⠀⠀⠀⠀⠀⣿⠈⢧⠀
⠀⠘⣿⣿⠁⠀⠀⠀⠀⠀⠀⠘⣿⡛⣶⠀⠀⣠⠔⠒⠛⠒⠦⡀⠀⠀⠀⠀⣠⡤⠶⠤⢤⣀⠀⠀⠀⢀⣏⡄⠀⠀⠀⠀⠀⡀⣿⡆⠈⣧
⣠⡾⠛⣿⣿⣧⠀⠀⠀⠀⢸⣿⠾⢿⡿⠀⣰⠃⠀⠀⠀⠀⠀⢹⡄⠀⠀⡼⠁⠀⠀⠀⠀⠈⠙⣦⠀⢸⣿⡇⣾⣣⡀⠀⢰⣿⣿⣿⣤⠾
⡟⠀⠀⠻⣿⡟⢷⡄⣤⡀⠈⣿⡀⣸⠇⠀⠏⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⡇⢀⡀⠀⠀⠀⠀⢀⡟⠀⠀⠋⣿⣿⣿⡇⣠⣿⠿⠛⢷⡀⠀
⠀⠀⠀⠀⣿⣇⣨⣿⣿⣿⣦⣽⣷⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠃⠀⠙⠢⠤⠤⠴⢾⠀⠀⠀⠀⢸⣷⣿⣿⠟⠁⠀⠀⠈⣧⠀
⠀⠀⠀⠀⠈⠉⠉⠁⠈⠉⠈⢉⣿⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⣿⠀
*/ #include <bits/stdc++.h>
using namespace std;
using ll = long long int;
using ld = long double;
using PII=pair<ll,ll>;
using PIII=pair<int,pair<int,int>>;
const ld ESP = 1e-10;
const ld PI = acosl(-1);
const int N=2e5+10;
const int M=1e6+10;
const int mod = 1000000007;
// const int mod = 998244353;
//随机化
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> Tp(1, 100);
// cout<<fixed<<setprecision(10);
void solve(){
int n;
cin>>n;
vector<vector<int>> dp(1<<n,vector<int>(n+1,0));
vector<vector<int>> dmx(1<<n,vector<int>(n+1,-1));
vector<vector<int>> dmi(1<<n,vector<int>(n+1,1e9));
int c[n][n];
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>c[i][j];
}
}
int mask=1<<n;
for(int i=0;i<mask;i++){
int cnt=__builtin_popcount(i);
if(cnt>=4){
for(int j=0;j<n;j++){
if(i>>j&1){
int res=1e9;
int mxf=1e9,mif=0;
for(int k=0;k<n;k++){
if((i>>k&1)&&j!=k){
if(c[k][j]>dmx[i^(1<<j)][k]){
if(res>dp[i^(1<<j)][k]+dmx[i^(1<<j)][k]){
res=dp[i^(1<<j)][k]+dmx[i^(1<<j)][k];
mxf=c[k][j];
mif=dmi[i^(1<<j)][k];
}
}
else if(c[k][j]<dmi[i^(1<<j)][k]){
if(res>dp[i^(1<<j)][k]-dmi[i^(1<<j)][k]+2*c[k][j]){
res=dp[i^(1<<j)][k]-dmi[i^(1<<j)][k]+2*c[k][j];
mxf=dmx[i^(1<<j)][k];
mif=c[k][j];
}
}else{
if(res>dp[i^(1<<j)][k]+c[k][j]){
res=dp[i^(1<<j)][k]+c[k][j];
mxf=dmx[i^(1<<j)][k];
mif=dmi[i^(1<<j)][k];
}
}
}
}
dp[i][j]=res;
dmx[i][j]=mxf;
dmi[i][j]=mif;
}
}
}else{
if(cnt==2){
for(int j=0;j<n;j++){
if(i>>j&1){
for(int k=0;k<n;k++){
if((i>>k&1)&&j!=k){
dmx[i][k]=c[j][k];dmi[i][k]=c[j][k];
dmx[i][j]=c[k][j];dmi[i][j]=c[k][j];
}
}
}
}
}else if(cnt==3){
for(int j=0;j<n;j++){
if(i>>j&1){
for(int k=0;k<n;k++){
if((i>>k&1)&&j!=k){
dmx[i][j]=max(dmx[i^(1<<j)][k],c[k][j]);
dmi[i][j]=min(dmi[i^(1<<j)][k],c[k][j]);
}
}
dp[i][j]=2*dmi[i][j];
}
}
}
}
}
int ans=1e9;
for(int i=0;i<n;i++){
ans=min(dp[mask-1][i],ans);
}cout<<ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _=1;
// cin>>_;
while(_--){
solve();
}
return 0;
} #include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;
const long long INF = LLONG_MAX / 2;
int n;
vector<vector<int>> g;
long long memo[1 << 16][17][2][2];
long long f(int s, int last, bool ga, bool aga) {
// 使用缓存
if (memo[s][last][ga][aga] != -1) {
return memo[s][last][ga][aga];
}
if (s == 0) {
// 所有节点都已访问
if (ga || aga) {
return INF;
}
return 0;
}
long long ans = INF;
for (int i = 0; i < n; i++) {
if (!(s & (1 << i))) {
continue;
}
int d = g[i][last];
int t = s ^ (1 << i);
long long x = f(t, i, ga, aga) + d;
if (last == n) {
ans = min(ans, x);
continue;
}
if (ga) {
x = min(x, f(t, i, false, aga));
}
if (aga) {
x = min(x, f(t, i, ga, false) + 2 * d);
}
ans = min(ans, x);
}
memo[s][last][ga][aga] = ans;
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
g.resize(n + 1, vector<int>(n + 1, 0));
// 读取邻接矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> g[i][j];
}
g[i][n] = 0; // 虚拟终点的边权为0
}
// 初始化备忘录
memset(memo, -1, sizeof(memo));
int s = (1 << n) - 1;
long long result = f(s, n, true, true);
cout << result << endl;
return 0;
} #include<bits/stdc++.h>
using namespace std;
#define int long long
int p[20][20];
int dp[1<<16][16][2][2];//mask,u,g,a
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve(){
int n;cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>p[i][j];
}
}
memset(dp,0x3f,sizeof(dp));
for(int i=0;i<n;i++) dp[1<<i][i][0][0]=0;
for(int mask=1;mask<(1<<n);mask++){
for(int u=0;u<n;u++){
if(!(mask&(1<<u))) continue;
for(int g=0;g<=1;g++){
for(int a=0;a<=1;a++){
if(dp[mask][u][g][a]==INF) continue;
for(int v=0;v<n;v++){
if(mask&(1<<v)) continue;
int newmask=mask|(1<<v);
dp[newmask][v][g][a]=min(dp[newmask][v][g][a],dp[mask][u][g][a]+p[u][v]);
if(!g) dp[newmask][v][1][a]=min(dp[newmask][v][1][a],dp[mask][u][g][a]);
if(!a) dp[newmask][v][g][1]=min(dp[newmask][v][g][1],dp[mask][u][g][a]+2*p[u][v]);
}
}
}
}
}
int ans=INF;
for(int i=0;i<n;i++) ans=min(ans,dp[(1<<n)-1][i][1][1]);
cout<<ans;
}
signed main(){
std::ios_base::sync_with_stdio(false);
std::cin.tie(nullptr);
int t=1;
// cin>>t;
while(t--){
solve();
}return 0;
} dp[sta][i][0] = min(dp[sta ^ (1 << i)][jp][0] + p[jp][i], dp[sta][i][0]); dp[sta][i][1] = min(dp[sta ^ (1 << i)][jp][0], dp[sta][i][1]); dp[sta][i][1] = min(dp[sta ^ (1 << i)][jp][1] + p[jp][i], dp[sta][i][1]); dp[sta][i][2] = min(dp[sta ^ (1 << i)][jp][0] + p[jp][i] * 2, dp[sta][i][2]); dp[sta][i][2] = min(dp[sta ^ (1 << i)][jp][2] + p[jp][i], dp[sta][i][2]); dp[sta][i][3] = min(dp[sta ^ (1 << i)][jp][1] + p[jp][i] * 2, dp[sta][i][3]); dp[sta][i][3] = min(dp[sta ^ (1 << i)][jp][2], dp[sta][i][3]); dp[sta][i][3] = min(dp[sta ^ (1 << i)][jp][3] + p[jp][i], dp[sta][i][3]);做完了。