一類適合記憶化搜尋的區間dp

potential-star發表於2024-03-27

https://www.luogu.com.cn/problem/P5752

https://codeforces.com/contest/598/problem/E

cf這個題考慮dp預處理,狀態是三維的,轉移是分割方案和所分塊需要獲得的巧克力數量。最後題目多次詢問可以o(1)快速查詢的

// Problem: E. Chocolate Bar
// Contest: Codeforces - Educational Codeforces Round 1
// URL: https://codeforces.com/contest/598/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
# define int long long
#define ull unsigned long long
#define pii pair<int,int>

#define baoliu(x, y) cout << fixed << setprecision(y) << x
#define endl  "\n"
#define debug1(x) cerr<<x<<" "
#define  debug2(x) cerr<<x<<endl
const int N = 35;
const int M = 1e6 + 10;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
int n, m,k;
int dp[N][N][N*N];

int a[N];
//考慮區間dp,記憶化搜尋
//提前預處理答案,O(1)查詢
//30*30*900(狀態)*(60*30)轉移=48600000*30(1.2e8)
//不會跑滿,加上記憶化和行列地位對等的剪枝
int dfs(int x,int y,int cnt){
	if(cnt==0||x*y==cnt)return 0;
	int &res=dp[x][y][cnt];
	//res=1e18;
	if(res!=-1)return res;
	
	if(dp[y][x][cnt]!=-1)return res=dp[y][x][cnt];
	res=1e18;
	for(int i=1;i<=x-1;i++){
		int now=cnt;
		for(int c=0;c<=now;c++){
			res=min(res,dfs(i,y,c)+dfs(x-i,y,now-c)+y*y);
		}
	}
	for(int i=1;i<=y-1;i++){
		int now=cnt;
		for(int c=0;c<=now;c++){
			res=min(res,dfs(x,i,c)+dfs(x,y-i,now-c)+x*x);
		}
	}
	dp[y][x][cnt]=res;
	return res;
}
void solve(){
	cin>>n>>m>>k;
	cout<<dfs(n,m,k)<<endl;
}
signed main() {
    cin.tie(0);
    
    ios::sync_with_stdio(false);
memset(dp,-1,sizeof dp);
    int t;
   cin>>t;
    // t=1;
    while (t--) {
solve();
    }
    return 0;
}

相關文章