朕今晚心血来潮,决定好好宠幸一下评测机爱妃,结果差一点AC
查看原帖
朕今晚心血来潮,决定好好宠幸一下评测机爱妃,结果差一点AC
935976
Amoribus楼主2024/8/9 21:05

dfs+dp,思路如下 目前的问题是求ans,使用A只能拿95分,使用B就能AC,这是什么原因?

/*
一、DFS选行 i:x~n-r+k 25000次 
二、Dp选列 c^3 16*16*16=4096 4e3*2.5e4=1e8
	1.状态 dp[y][i] 选y列 以i列结尾的最小分值 
	2.初始化:0x3f无穷大  dp[1][i]=yy[i]第i列的纵向差 
	3.状态转移方程:dp[y][i]=min(dp[y][i],dp[y-1][j]+xx[j][i]+yy[i])
	y:2~c i:y~m j:y-1~i-1
	4.答案 dp[c][i] i:c~m 
	找到一种行组合的最优解
	5.找所有组合的最优解 
*/
#include<bits/stdc++.h>
using namespace std;
int n,m,r,c,a[17][17],ans=INT_MAX,ys[17],dp[17][17],xx[17][17],yy[17],b[17][17];
void dfs(int k,int x)//第k个从第x行开始选 
{
	if(k>r) 
	{
		int i,j,h,y,ans1=INT_MAX;
		memset(dp,0x3f,sizeof(dp));
		memset(xx,0,sizeof(xx));
		memset(yy,0,sizeof(yy));
		for(i=1;i<=r;i++)
			for(j=1;j<=m;j++) b[i][j]=a[ys[i]][j];
		for(i=1;i<m;i++)
			for(j=i+1;j<=m;j++) 
				for(h=1;h<=r;h++) xx[i][j]+=abs(b[h][i]-b[h][j]);
		for(j=1;j<=m;j++) 
			for(h=1;h<r;h++) yy[j]+=abs(b[h][j]-b[h+1][j]);
		for(j=1;j<=m;j++) dp[1][j]=yy[j];
		for(y=2;y<=c;y++)
			for(i=y;i<=m;i++)
			{
				for(j=y-1;j<=i-1;j++)
					dp[y][i]=min(dp[y][i],dp[y-1][j]+xx[j][i]+yy[i]);
				//**A**if(y==c) ans1=min(ans1,dp[y][i]);
			}
		//**B**for(i=c;i<=m;i++) ans1=min(ans1,dp[c][i]);
		ans=min(ans,ans1);			
		return;
	}
	for(int i=x;i<=n;i++) ys[k]=i,dfs(k+1,i+1);
}
int main()
{
	int i,j;
	cin>>n>>m>>r>>c;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++) cin>>a[i][j];
	dfs(1,1);//枚举行组合 第一个选第一行 
	cout<<ans;
	return 0;
}

2024/8/9 21:05
加载中...