状压+DP10分求助,ACon#1,#10,其他全WA
查看原帖
状压+DP10分求助,ACon#1,#10,其他全WA
768530
Expert_Dream楼主2023/10/14 08:18
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
#define fir first
#define se second
#define ull unsigned long long
#define endl "\n"
using namespace std;
const int N = 20;
int n,m,r,c;
int a[N][N];
int dp[N][N];
/*
遍历完前i列,已经选了j个
dp[i][j] = min(dp[i][j],dp[1~i-1][j-1])

*/
signed main(){
	cin >> n >> m >> r >> c ;
	for(int i =1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			scanf("%lld",&a[i][j]);
		}
	}
	//1、枚举状态,选那几行
	int ans=0x3f3f3f3f;
	for(int i = 0;i < (1<<(n+1));i++){//时间复杂度:1e5枚举行的状压
		int cnt=0;
		for(int j = 0;j <= 20;j++){
			if((i>>j)&1)cnt++;
		}
		if(cnt==r){//时间复杂度1e4		
			memset(dp,0x3f,sizeof dp);
			vector<int> s,v;
			for(int j = 0 ;j <= 20;j++) if((1<<j)&i) s.push_back(j+1);
			for(int k = 1;k <= m;k++){//预处理
				int sum=0;
				int lst=-1;
				for(auto j:s){
					if(lst == -1){
						lst=j;
					}else{
						sum += abs(a[j][k]-a[lst][k]);
						lst=j;
					}					
				}	
				v.push_back(sum);			
			}
			dp[0][0]=0;
			for(int i = 1;i <= m;i++){
				for(int j = 1;j <= i;j++){
					for(int k = 0;k <= i-1;k++){
						int num=0;
						for(auto p:s){
							num+=abs(a[p][i]-a[p][k]);
						}
						dp[i][j]=min(dp[i][j],dp[k][j-1]+(j==1?0:num)+v[i-1]);
					}
				}
			}
			ans=min(ans,dp[n][c]);
		} 
	}cout<<ans;
	return 0;
}

2023/10/14 08:18
加载中...