状压dp 10分求助
查看原帖
状压dp 10分求助
315205
Kniqht楼主2022/9/15 21:42
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<utility>
#include<queue>
#include<cmath>
#define st state[i]
#define int long long
using namespace std;
const int N=17,M=1e5+10;
int n,m,r,c,cnt,g[N][N];
int f[N][N][N],state[N];
bool check(int x){
    int res=0;
    for(int i=0;i<m;i++)    
        if(x>>i&1) res++;
    return (res==c);
}
int get(int p,int x){
	int res=0,last=-1;
	for(int i=0;i<m;i++)	
		if(x>>i&1){
			if(last!=-1) res+=abs(g[p][i]-g[p][last]);
			last=i; 
		}
	return res;
} 
int get1(int p,int now,int x){
	int res=0;
	for(int i=0;i<m;i++)
		if(x>>i&1) res+=abs(g[p][i]-g[now][i]);
	return res;
}
signed main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	scanf("%lld%lld%lld%lld",&n,&m,&r,&c);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++) scanf("%lld",&g[i][j]);
    for(int i=0;i<(1<<m);i++)	
    	if(check(i)) state[++cnt]=i;
    memset(f,127,sizeof(f));int now=f[0][0][0];
    int Inf=now;
    for(int i=1;i<=cnt;i++)
    	for(int j=0;j<n;j++){
    		f[1][j][i]=get(j,st);
    		if(r==1) now=min(now,f[1][j][i]);
		}
    for(int i=1;i<=cnt;i++)
    	for(int j=2;j<=r;j++)
    		for(int c1=0;c1<n;c1++){
				for(int k=0;k<c1;k++){
					if(f[j-1][k][i]==Inf) continue;
					int tmp=get1(c1,k,st),t1=get(c1,st);
					if(f[j][c1][i]>f[j-1][k][i]+tmp+t1){
						f[j][c1][i]=f[j-1][k][i]+tmp+t1;
						if(j==r) now=min(now,f[j][c1][i]);
					} 
				} 
			}
	printf("%lld",now);
	return 0;
}

2022/9/15 21:42
加载中...