acdream 1086 晴天小猪爱61 (贪心+背包)

题意:

给出一个数字,要把这个数字分成尽量少的含有61的数。

题解:

首先对于n>=6161的数,可以得出一个结论,肯定能分成***61  61**这样的形式。那么对于小于6161的数可以考虑用完全背包,中途记录状态就好了。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1000000007;
const double eps = 1e-9;
const int maxn = 6200;
int dp[maxn];
int pre[maxn];
vector<int>num, ans;

void Init(){
	for (int i = 0; i <= 99; i++){
		num.push_back(i * 100 + 61);
		if (i <= 61)
			num.push_back(61 * 100 + i);
	}
	for (int i = 0; i <= 9; i++){
		for (int j = 0; j <= 9; j++){
			num.push_back(i * 1000 + 61 * 10 + j);
		}
	}
}

bool had61(int n){
	int u, v;
	u = n % 10;
	while (n){
		v = n % 10;
		if (v == 6 && u == 1)
			return true;
		n /= 10;
		u = v;
	}
	return false;
}

int main(){
	//freopen("E:\\read.txt","r",stdin);
	int T, n, W, a, b;
	Init();
	scanf("%d", &T);
	while (T--){
		scanf("%d", &W);
		if (had61(W)){
			printf("1 %d\n", W);
			continue;
		}
		if (W >= 6161){
			for (a = 6100; a <= 6199; a++){
				b = W - a;
				if (b % 10 == 1 && b / 10 % 10 == 6)
					break;
			}
			printf("2 %d %d\n", a, b);
			continue;
		}
		n = num.size();
		memset(dp, 0x3f, sizeof dp);
		memset(pre, -1, sizeof pre);
		dp[0] = 0;
		for (int i = 0; i < n; i++){
			for (int j = num[i]; j <= W; j++){
				if (dp[j]>dp[j - num[i]] + 1){
					dp[j] = dp[j - num[i]] + 1;
					pre[j] = j - num[i];
				}
			}
		}
		if (dp[W] == oo) printf("0\n");
		else{
			ans.clear();
			int u, v;
			u = W;
			while (pre[u] != -1){
				v = pre[u];
				ans.push_back(u - v);
				u = v;
			}
			n = ans.size();
			printf("%d", ans.size());
			for (int i = 0; i < n; i++)
				printf(" %d", ans[i]);
			puts("");
		}
	}
	return 0;
}
/*
1000
789456132
*/



你可能感兴趣的:(acdream 1086 晴天小猪爱61 (贪心+背包))