• Luogu P1874 快速求和 DP


    传送门
    dp[i][j]表示前前i位组成数字k的最小次数,预处理出s[i][j]表示数位i到j表示的数字
    状态转移方程即为:dp[i][k] = min(dp[i][k], dp[j - 1, k - s[i][j]] + 1).
    dp[0][0] = 0, 其余为大数字
    当遇到s[i][j]大于n时,将s[i][j]设为一个大数,以免爆int

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define INF 1000000
    using namespace std; 
    
    int num[100], len, n;
    int dp[50][100001], s[100][100]; //前i位组成数字k的最小次数
    //dp[i][k] =  min(dp[i][k], dp[i - 
    
    void read(){
    	char ch = getchar();
    	while(ch < '0' || ch > '9') ch = getchar();
    	while(ch >= '0' && ch <= '9') num[++len] = ch - '0', ch = getchar();
    	return;
    }
    
    int main(){
    	for(int i = 0; i < 50; i++){
    		for(int j = 0; j < 100001; j++){
    			dp[i][j] = 1000000;
    		}
    	}
    	for(int i = 0; i < 100; i++){
    		for(int j = 0; j < 100; j++){
    			s[i][j] = 1000000;
    		}
    	}
    	read();
    	scanf("%d", &n);
    	
    	//[i, i+l]数字,若大于100000设为INF 
    	for(int i = 1; i <= len; i++){
    		s[i][i] = num[i];
    	}
    	for(int l = 1; l <= len; l++){
    		for(int i = 1; i + l <= len; i++){
    			int tmp = s[i][i+l-1]*10 + num[i + l];
    			if(tmp > 100000ll) s[i][i+l] = INF;
    			else s[i][i+l] = tmp;
    		}
    	}
    	
    //	for(int i = 1; i <= len; i++){
    //		for(int j = i; j <= len; j++){
    //			printf("s[%d][%d] = %d
    ", i, j, s[i][j]);
    //		}
    //	}
    	
    	dp[0][0] = 0;
    	
    	for(int i = 1; i <= len; i++){
    		for(int j = 1; j <= i; j++){
    //			printf("%d %d
    ", i, j);
    			int val = s[j][i];
    //			printf("val = %d
    ", val);
    			if(s[j][i] > 100000) continue;
    			for(int k = val; k <= n; k++){
    //				printf("k = %d
    ", k);
    //				printf("%d %d    %d %d
    ", j - 1, k - val, i, k);
    				if(dp[j - 1][k - val] + 1 < dp[i][k]){
    					dp[i][k] = dp[j - 1][k - val] + 1;
    //					printf("dp[%d][%d] = %d
    ", i, k, dp[i][k]);
    				}
    //				dp[i][k] = min(dp[i][k], dp[j - 1][k - val] + 1);
    			}
    //			int l = i - j + 1;
    		}
    	}
    	if(dp[len][n] > 100) dp[len][n] = 0;
    	printf("%d", dp[len][n] - 1);
    	return 0;
    }
    
  • 相关阅读:
    ADO.NET批量插入数据方法比较
    Thread was being aborted 分析与解决
    第三方刻录软件介绍
    ASP.NET登陆SQL Server数据库
    word 2010页眉页码从第三页开始设置
    误删除、误格式化后的灾难恢复方案
    Asp.Net4.0新特性概述
    ArcGIS Server的切图原理深入
    ArcGIS的缓存技术
    ArcGIS Server操作Mxd文件详细讲解
  • 原文地址:https://www.cnblogs.com/asdf1229/p/13501867.html
Copyright © 2020-2023  润新知