举个例子,如果
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
// n个点: * * * * * * * * *
// 先考虑一个衍生问题,把n个点分成尽量多的组,并且每个组分到的点数不相同,我们
// 要找出一种分法。
// dp[x][y] x个点分成尽量多的组,每组点数不同,最大组点数为y,分出的最多组数。
/*
y=x dp[x][x] = 1
y<x dp[x][y] = 0 if max{i<y}(dp[x-y][i]) == 0
1+max{i<y}(dp[x-y][i]) if max{i<y}(dp[x-y][i]) != 0
y>x dp[x][y] = 0
*/
//
int dp[102][102];
int main() {
memset(dp, 0, sizeof(dp));
int n;
cin>>n;
// 动态规划
for(int x=1;x<=n;x++){
for(int y=1;y<x;y++){
int mx = 0;
for(int i=1;i<y;i++){
if(mx<dp[x-y][i])
mx = dp[x-y][i];
}
if(mx)
dp[x][y] = mx + 1;
}
dp[x][x] = 1;
}
// 如果对于dp[n][1~9]均为0,则没有可行方案
int mx_y = 0;
for(int i=1;i<=9;i++){
if(dp[n][mx_y]<dp[n][i])
mx_y = i;
}
if(mx_y==0){
cout<<-1;
return 0;
}
// 否则重构出一个解。mx_y目前是能使分组数最多的分组方案中,
// 最大那个组的点数(当然我们只考虑范围1~9,更大的根本不考虑)
vector<int> solution;
int res = n-mx_y;
solution.push_back(mx_y);
while(res){
int mx_yy = 0;
for(int i=0;i<mx_y;i++)
if(dp[res][mx_yy]<dp[res][i])
mx_yy = i;
mx_y = mx_yy;
solution.push_back(mx_y);
res-=mx_y;
}
// 为了得到原题的解,需要对我们衍生问题的解进行改进 | | | |
// 此时solution中就是分组的各组点数,降序排列。
// 现在进一步改进,把点的差距拉开,重心尽量前移,
// 例如:8 4 3 => 9 4 2 => 9 5 1
int len = solution.size();
int p = 0, q=len-1;
int max_left=9,min_right=1;
while(p!=q){
if(solution[p]==max_left){
max_left--;
p++;
}else if(solution[q]==min_right){
min_right++;
q--;
}else{
solution[p]++;
solution[q]--;
}
}
// 现在可以通过solution计算最终解
int final = 0;
for(int i:solution){
final*=10;
final+=i;
}
cout<<final;
return 0;
}
// 64 位输出请用 printf("%lld") package main
import "fmt"
var m = make(map[int]int) //m保存位数信息
var use = make(map[int]bool) // use保存某一个数是否被使用过,保证不重复
func panduan(a int, wei int) (string, bool) {
if a == 1 || a == 2 {
return fmt.Sprintf("%d", a), true
}
res := ""
for i := 9; i >= 1; i-- {
if use[i] {
continue
}
if a-i > 0 {
as := a - i
if m[as] == wei-1 {
use[i] = true
temp, ok := panduan(as, wei-1)
if ok {
res = fmt.Sprintf("%d%s", i, temp)
return res, true
} else {
use[i] = false
}
}
}
}
return "", false
}
func main() {
// 读取一个int数字
var a int
fmt.Scan(&a)
if a > 45 {
fmt.Println(-1)
return
}
if a == 45 {
fmt.Println(987654321)
return
}
for i := 1; i < 45; i++ {
switch {
case i == 1 || i == 2:
m[i] = 1
case i >= 3 && i < 6:
m[i] = 2
case i >= 6 && i < 10:
m[i] = 3
case i >= 10 && i < 15:
m[i] = 4
case i >= 15 && i < 21:
m[i] = 5
case i >= 21 && i < 28:
m[i] = 6
case i >= 28 && i < 36:
m[i] = 7
case i >= 36 && i < 45:
m[i] = 8
case i == 45:
m[i] = 9
}
}
res, ok := panduan(a, m[a])
if ok {
fmt.Println(res)
} else {
fmt.Println(-1)
}
} n = int(input()) f=[] for i in range(11): f.append([]) for j in range(46): f[i].append(0) if n>45: print(-1) else: for i in range(1, 10): for j in range(0, n+1): f[i][j]=f[i-1][j] if (j>=i): bias = pow(10,len(str(f[i-1][j-i]))) if f[i-1][j-i] == 0: bias = 1 f[i][j]=max(f[i][j],i*bias+f[i-1][j-i]) print(f[9][n])DP,不难发现,大数总是在小数之前出现,f[i][j]表示前i个数,和是j的最大表示。f[i][j]=max{f[i-1][j],concatenate(i,f[i-1][j-i])}
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
int n = in.nextInt();
if (n > 45) {
System.out.println(-1);
return;
} else if (n < 3) {
System.out.println(n);
return;
} else {
int res = 0;
ArrayList<Integer> nums = new ArrayList<>();
int min = 1;
int rest = 0;
while (n != 0) {
nums.add(min);
n -= min;
min++;
if ((n - min) < (min + 1)) {
if (n<10 && n>0){
nums.add(n);
} else {
rest = n - 9;
nums.add(9);
}
break;
}
}
int times = 1;
for (int i = nums.size() - 2; i >= 0; i--) {
int cur = nums.get(i);
if (rest <= 9 - times - cur) {
nums.set(i, cur + rest);
break;
} else {
nums.set(i, 9 - times);
rest = rest - (9 - times - cur);
times++;
}
}
for (int i = 0; i < nums.size(); i++) {
res += nums.get(i) * Math.pow(10, i);
}
System.out.println(res);
}
}
} 维护状态,每次找到最小还原次数,然后向后向前遍历直到遇到0(Max_Value)#include <iostream>
#include <vector>
#include <set>
using namespace std;
int ret = -1;
void dfs(set<int>& cur, int i, int n, int sum) {
if (i > 9) {
if (sum == n) {
int tmp = 0;
for (auto it = cur.rbegin(); it != cur.rend(); ++it) {
tmp = tmp * 10 + *it;
}
ret = max(ret, tmp);
}
return;
}
if (i+sum <= n) {
cur.insert(i);
dfs(cur, i+1, n, sum + i);
cur.erase(i);
}
dfs(cur, i+1, n, sum);
}
int main() {
int n;
cin >> n;
if (n > 45) {
std::cout<<ret<<std::endl;
}
else {
set<int> s;
dfs(s, 1, n, 0);
std::cout<<ret<<std::endl;
}
}
// 64 位输出请用 printf("%lld")
#include<bits/stdc++.h>
using namespace std;
vector<string> v;
string s = "";
void dfs(int i, int n, int sum) {
if(i >= 10) {
if(sum == n) {
v.push_back(string(s));
}
return ;
}
if(sum > n) {
return ;
}
if(n - sum > (i + 9) * (10 - i) / 2)
return ;
dfs(i + 1, n, sum);
s += (i + '0');
dfs(i + 1, n, sum + i);
s.pop_back();
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
if(n > 45) {
cout << -1 << '\n';
return 0;
}
dfs(1, n, 0);
if(v.size() == 0) {
cout << -1 << '\n';
}
else {
sort(v[0].begin(), v[0].end(), greater<char>());
string res = v[0];
for(int i = 1;i < v.size();i++) {
if(res.size() < v[i].size()) {
sort(v[i].begin(), v[i].end(), greater<char>());
res = v[i];
}
else if(res.size() == v[i].size()) {
sort(v[i].begin(), v[i].end(), greater<char>());
if(res.compare(v[i]) < 0) {
res = v[i];
}
}
}
cout << res << '\n';
}
return 0;
}