#include <stdio.h>
int main()
{
int postage[15]={8,8,8,8,8,10,10,10,10,18,18,18,18,18,18};
int dp[189]={1}; //组合出来的邮资小于等于188(角)
int i,j;
for(i=0;i<15;i++)
{
for(j=188;j>=postage[i];j--)
{
if(dp[j-postage[i]]!=0)dp[j]=1;
}
}
j=0;
for(i=8;i<=188;i++)if(dp[i]!=0)j++; //组合不出来8角以下的
printf("%d",j);
} #include<stdio.h>
int main()
{
int i,j,k,num=0;//张数
float sum[1000];
for(i=0;i<=5;i++)
for(j=0;j<=4;j++)
for(k=0;k<=6;k++)
{
if(i==0&&j==0&&k==0) continue;//0张邮票不参与
sum[num++]=0.8*i+1*j+1.8*k;
}
for(i=0;i<num;i++)//去重
{
for(j=i+1;j<num;j++)
if(sum[i]==sum[j])
{
sum[j]=sum[num-1];//把最后一个数拿过来
num--;j--;//个数减一,在从当前位置开始
}
}
printf("%d",num);
}
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> st;
for(int i=0;i<=5;i++)
{
for(int j=0;j<=4;j++)
{
for(int k=0;k<=6;k++)
{
if(i==0&&j==0&&k==0) continue;
else st.insert(i*8 + j*10 + k*18);
}
}
}
cout<<st.size()<<endl;
return 0;
}
//用set最方便,直接去掉重复的,也不用开辟很大的数组,空间上效率高得多。
import java.util.HashSet;
import java.util.Set;
public class Main { public static void main(String[] args) {
int x=8;
int y=10;
int z=18;
int sum=0;
HashSet set=new HashSet();
for(int i=0;i<=5;i++){ for(int j=0;j<=4;j++){ for(int k=0;k<=6;k++){ sum=i*x+j*y+k*z; set.add(sum); } }
}
System.out.println(set.size()-1); } } #include <cstdio>
#include <iostream>
#include <algorithm>
#include <map>
#include <cmath>
#include <cctype>
using namespace std;
int num[1000];
int main(){
int a,b,c;
int j = 0;
for(int a = 0;a <= 5;a++)
for(int b = 0;b <= 4;b++)
for(int c = 0;c <= 6;c++){
num[j++] = a*8+b*10+c*18;
}
sort(num,num+j);
int sum = 0;
for(int i = 1;i < j;i++){
if(num[i]!=num[i-1])
sum++;
}
cout<<sum;
}
解题思路: 1.根据题意,邮票的组合情况有三种,分别是只有一种邮票,只有两种邮票和三种邮票都有的情况。 求解方法就是有几种邮票就有几层循环。 2.利用集合的性质,元素是不会有重复的,所以集合中元素的个数就是答案。 3.看了一下前面大佬的答案,忽然才想到,只要求算出个数的话,可以把小数化为整数,都扩大十倍 是不会有影响的,不同的数也不会变成相同,用小数算的话其实是有风险的,double和float要小 心谨慎地使用,如果元素精度高,在set中会严格按照你开的set的精度来排序,但是如果你输出 的时候精度没有达到那么高就会被四舍五入,那么你会发现set中居然存在两个相同的元素,其实他 们是不同的,后面的小数不同。 这是本人第一次写题解,如果有什么不正确的地方,欢迎大家批评指正。
#include <stdio.h>
int main(){
int th[200]={0};
for(int i=0;i<=5;i++){
for(int j=0;j<=4;j++){
for(int k=0; k<=6;k++){
th[4*i+5*j+9*k]=1;
}
}
}
int num=0;
for(int i=0;i<200;i++){
if(th[i]==1){
num++;
}
}
printf("%d",num-1);
}
思路: 把每种方案映射到数组中,重复的依旧记作1,统计方案的个数。
#include<iostream>
using namespace std;
int dp[189];
void Initial()
{
for (int i = 0; i < 189; i++) //初始dp数组
{
if (i == 0) dp[i] = 1;
else dp[i] = 0;
}
}
int main()
{
Initial();
int a[] = {0,8,8,8,8,8,10,10,10,10,18,18,18,18,18,18};
for(int i=1;i<16;i++) //0-1背包变形
for (int j = 188; j >= a[i]; j--)
{
dp[j] = dp[j] + dp[j - a[i]];
}
int count = 0;
for (int i = 1; i < 189; i++) //统计1-188能装满的方案数
if (dp[i] != 0) count++;
cout << count << endl;
} #include <iostream>
using namespace std;
#define max 8 * 5 + 10 * 4 + 18 * 6 //最大邮资数(单位:角)
int main() {
int count[max + 1] = {0}; //统计每种邮资可能情况数
for (int i = 0; i <= 5; i++)
for (int j = 0; j <= 4; j++)
for (int k = 0; k <= 6; k++) {
int value = 8 * i + 10 * j + 18 * k; //邮资值(单位:角)
if (value != 0)count[value]++;
}
int num = 0; //邮资种数
for (int i = 1; i <= max; i++)
if (count[i] > 0)
num++; //邮资值存在,邮资种数增1
cout << num;
} #include<bits/stdc++.h>
#include <unordered_map>
#include <vector>
using namespace std;
class Solution {
private:
set<int>appeared;
vector<vector<int>>posts;
void backtrack(int pos, int sum) {
if (pos >= 3)return;
for (int i = 0; i < posts[pos].size(); i++) {
sum += posts[pos][i];
if (!appeared.count(sum)) {
appeared.insert(sum);
}
backtrack(pos + 1, sum);
}
}
public:
int postMoneyKind() {
posts = {
{0, 8, 8, 8, 8, 8},
{0, 10, 10, 10, 10},
{0, 18, 18, 18, 18, 18, 18}
};
backtrack(0, 0);
return appeared.size();
}
};
int main() {
Solution sol;
cout << sol.postMoneyKind()-1 << endl;
return 0;
}