[2016-03-07][UVALive][4292][Matchsticks]
[2016-03-07][UVALive][4292][Matchsticks]
- 时间:2016-03-06 14:15:55 星期日
- 题目编号:[UVALive][4292][Matchsticks] F - F
- 题目大意:给定若干跟火柴,求这些火柴能拼成的最大的数字和最小的数字
- 输入:数据组数c
- 每组数据一个整数,表示火柴数目
- 输出:最小数字和最大数字
- 方法:
- 方法1:贪心,最大位数,如果数目是偶数,直接111111...,如果是奇数就是711111...
- 最小位数,贪心,大于16位的,一定是选择8,否则的话,会位数会多,小于16的部分,分类讨论
- 方法2:最大值还是一样,
- 最小值,先dfs一遍,得到最小位数,然后IDA*枚举每一位上的数字,得到最小值
- 方法3:最大值一样
- 最小值dp dp[i]表示i根火柴的能表示的最小值,a[k]表示第k个数字消耗的火柴,dp[i] = min(dp[i],dp[i - a[k]] + k);
- 解题过程遇到问题:
- Min声明的时候数组只开了11(之前是为了计算每个数字的次数,后来改了,忘记增加),WA了
- (然后之前也弄了Max对最大值的每一位计数,没删除,因为Min和Max连在一起,当时没WA,整理代码的时候,删除了Max,就WA了)
- dp的时候,数值是可以超过int的范围的,然后改成LL之和,各种连带错误(输出,初始化)忘记改
//IDA* #ifdef _WORK_ #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x)) #define FORD(x,y,z) for(int (x)=(y);(x)>=(z);--(x)) #define FOR2(x,y,z) for((x)=(y);(x)<(z);++(x)) #define FORD2(x,y,z) for((x)=(y);(x)>=(z);--(x)) int cost[] = {6,2,5,5,4,5,6,3,7,6}; // 0,1,2,3,4,5,6,7,8,9 int n,Min[110],minct;//最小位数 int dfs(int left,int ct){ if(left == 0){ minct = ct; return 1; } FORD(i,7,2){ if(left >= i && dfs(left - i,ct + 1)){ return 1; } } return 0; } int dfsmin(int left,int cur){ if(cur == minct){ return left == 0; } //IDA* 剪个枝,不然会T if(left + 7*cur > 7*minct) return 0; if(cur && left >= cost[0]){ if(dfsmin( left - cost[0],cur + 1 )){ Min[cur] = 0; return 1; } } FOR(i,1,10){ if(left >= cost[i]){ if(dfsmin( left - cost[i],cur + 1)){ Min[cur] = i; return 1; } } } return 0; } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T; scanf("%d",&T); while (T--){ scanf("%d",&n); dfs(n,0);//求最少位数 dfsmin(n,0);//求最少位数下最小的答案 FOR(i,0,minct) putchar('0' + Min[i]); putchar(' '); if(n&1){ putchar('7'); n -= 3; } FOR(i,0,n/2) putchar('1'); putchar('\n'); } return 0; } #endif |
//dp #ifdef _WORK_ #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x)) #define FORD(x,y,z) for(int (x)=(y);(x)>=(z);--(x)) #define FOR2(x,y,z) int (x);for((x)=(y);(x)<(z);++(x)) #define FORD2(x,y,z) int (x);for((x)=(y);(x)>=(z);--(x)) int n,a[] = {6,2,5,5,4,5,6,3,7,6}; LL dp[110] = {0x3f3f3f3f,0x3f3f3f3f,1,7,4,2,6,8,}; void inidp(){ memset(dp+8,0x7f,sizeof(LL)*(100)); FOR(i,8,101){ FOR(j,0,10){ dp[i] = min(dp[i],dp[i - a[j]]*10 + j); } } } int main(){ //freopen("out.txt","w",stdout); inidp(); int T; scanf("%d",&T); while (T--){ scanf("%d",&n); printf("%lld ",dp[n]); if(n&1){ putchar('7'); n -= 3; } FOR(i,0,n/2) putchar('1'); putchar('\n'); } return 0; } #endif |
浙公网安备 33010602011771号