7744问题的两种解法

aabb问题又名7744问题,因为这个问题在规定范围内只有这一个解。(作者自己编的解释)

问题:输出所有形如aabb的4位数的完全平方数(即前两个数字相等,后两个数字相等)。

方法一:

#include

#include

int main()
 {
    for(int i=1;i<=9;i++)
    {
        for(int j=0;j<=9;j++)
        {
            int n=i*1100+j*11;
            int m=floor(sqrt(n)+0.5);
            if(m*m==n)
            printf("%d\n",n);
        }

    }
    return 0;

}

上面这个程序用到了两个库函数stdio.h和math.h。

其中floor(x)函数和sqrt(x)函数是存在于math.h库函数下的,分别用于求不超过x的最大整数和x的平方根。

floor(x+0.5)就是一个四舍五入的方法。读着可以自己尝试理解。

方法二:

#include

int main()
{
    for(int n=1;;n++)
    {
        int x=n*n;
        if(x<1000) continue;
        if(x>9999) break;
        int a=x/100;
        int b=x%100;
        if(a/10==a%10&&b/10==b%10)
        printf("%d\n",x);
    }
    return 0;
}

上面这个程序只用到了stdio.h函数,方便初学者,尤其是还不太了解可函数的人学习使用,整个程序也比较方便理解。读不懂的同学可以继续往下看。

“/”符号在C环境中也是除的意思,但是请注意前面的被赋值的变量的类型,a是int型,也就是整形,那么x/100求得的结果只取小数点前面的部分,也就是说,我写的这个程序中a就是题目中的aa,同理b的含义也好理解。"%"符号在C环境中代表的意思是取模,通俗的讲就是取余,这一点需要不懂的同学特别记忆一下。

接下来,再说明一下continue和break两个标识符的含义和作用。按照翻译,就不难理解,继续和停止。但请注意:continue是跳回for循环的开始“继续”,break是直接调出整个循环结构“停止”。也就是说,不管是执行了continue语句还是break语句,它后面的for循环里面那一部分都是不再执行直接跳过的,这一点不要搞错了。

明白了这两点,这个程序应该就没什么大问题了,当然,在一些小地方会有很多种写法。比如,我们在给for初始化的时候,直接将n的值赋为32,那吗,后面的程序中就不需要if(x<1000) continue;这个语句了,可见,使用continue语句可以帮我们减少计算,顺便偷个懒!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我来为您介绍一下。 1.暴力递归法 这种方法是通过递归的方式来解决01背包问题的。对于每个物品,我们可以选择将其放入背包或者不放入背包,然后再考虑下一个物品。当考虑完所有的物品后,我们就可以得到一个解,然后再从所有的解中选择一个最优解。这种方法的时间复杂度为O(2^n),其中n为物品的个数,因为对于每个物品,我们都有两种选择。 下面是使用暴力递归法实现01背包问题的代码: ```c #include <stdio.h> int max(int a, int b) { return a > b ? a : b; } int knapsack(int W, int wt[], int val[], int n) { if (n == 0 || W == 0) { return 0; } if (wt[n-1] > W) { return knapsack(W, wt, val, n-1); } return max(val[n-1] + knapsack(W-wt[n-1], wt, val, n-1), knapsack(W, wt, val, n-1)); } int main() { int val[] = {60, 100, 120}; int wt[] = {10, 20, 30}; int W = 50; int n = sizeof(val)/sizeof(val[0]); printf("Maximum value: %d", knapsack(W, wt, val, n)); return 0; } ``` 2.动态规划法 动态规划法是通过构建一个二维数组来解决01背包问题的。我们可以将物品放入背包中,或者不将其放入背包中。我们可以将二维数组中的每个元素看做是一个子问题的解,然后我们可以通过递推的方式来求解整个问题的解。此方法的时间复杂度为O(nW),其中n为物品的个数,W为背包的容量。 下面是使用动态规划法实现01背包问题的代码: ```c #include <stdio.h> int max(int a, int b) { return a > b ? a : b; } int knapsack(int W, int wt[], int val[], int n) { int dp[n+1][W+1]; for (int i = 0; i <= n; i++) { for (int w = 0; w <= W; w++) { if (i == 0 || w == 0) { dp[i][w] = 0; } else if (wt[i-1] > w) { dp[i][w] = dp[i-1][w]; } else { dp[i][w] = max(val[i-1] + dp[i-1][w-wt[i-1]], dp[i-1][w]); } } } return dp[n][W]; } int main() { int val[] = {60, 100, 120}; int wt[] = {10, 20, 30}; int W = 50; int n = sizeof(val)/sizeof(val[0]); printf("Maximum value: %d", knapsack(W, wt, val, n)); return 0; } ``` 3.回溯法 回溯法是通过搜索所有可能的解来解决01背包问题的。在搜索的过程中,我们可以将物品放入背包中,或者不将其放入背包中。如果当前的背包容量已经超过了背包的容量,或者已经考虑完所有的物品,那么就可以得到一个解。然后再从所有的解中选择一个最优解。这种方法的时间复杂度为O(2^n),其中n为物品的个数。 下面是使用回溯法实现01背包问题的代码: ```c #include <stdio.h> int max(int a, int b) { return a > b ? a : b; } void knapsack(int W, int wt[], int val[], int n, int curW, int curVal, int *maxVal) { if (curW > W) { return; } if (n == 0) { *maxVal = max(*maxVal, curVal); return; } knapsack(W, wt, val, n-1, curW, curVal, maxVal); knapsack(W, wt, val, n-1, curW+wt[n-1], curVal+val[n-1], maxVal); } int main() { int val[] = {60, 100, 120}; int wt[] = {10, 20, 30}; int W = 50; int n = sizeof(val)/sizeof(val[0]); int maxVal = 0; knapsack(W, wt, val, n, 0, 0, &maxVal); printf("Maximum value: %d", maxVal); return 0; } ``` 4.分支限界法 分支限界法是通过搜索所有可能的解来解决01背包问题的。在搜索的过程中,我们可以将物品放入背包中,或者不将其放入背包中。但是我们在搜索的过程中,可以使用一些策略来减少搜索的次数。例如,我们可以将物品按照单位重量的价值排序,然后先考虑价值高的物品。这种方法的时间复杂度取决于使用的策略,但是一般来说,它的时间复杂度可以达到O(nlogn)。 下面是使用分支限界法实现01背包问题的代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct Item { int val; int wt; double vw; } Item; int cmp(const void *a, const void *b) { Item *ia = (Item *)a; Item *ib = (Item *)b; return ib->vw - ia->vw; } int bound(Item items[], int n, int W, int curW, int curVal) { if (curW > W) { return 0; } int boundVal = curVal; int j = n; int totW = curW; while ((j < n) && (totW + items[j].wt <= W)) { totW += items[j].wt; boundVal += items[j].val; j++; } if (j < n) { boundVal += (W - totW) * items[j].vw; } return boundVal; } void knapsack(Item items[], int n, int W, int *maxVal) { qsort(items, n, sizeof(Item), cmp); int curW = 0, curVal = 0; int i = 0; int boundVal = bound(items, n, W, curW, curVal); int Q[n]; Q[i] = 0; while (i >= 0) { int j = Q[i]; i--; if (j == n) { if (curVal > *maxVal) { *maxVal = curVal; } continue; } if (curW + items[j].wt <= W) { curW += items[j].wt; curVal += items[j].val; if (curVal > *maxVal) { *maxVal = curVal; } boundVal = bound(items, n, W, curW, curVal); if (boundVal > *maxVal) { i++; Q[i] = j+1; } curW -= items[j].wt; curVal -= items[j].val; } boundVal = bound(items, n, W, curW, curVal); if (boundVal > *maxVal) { i++; Q[i] = j+1; } } } int main() { Item items[] = {{60, 10, 6}, {100, 20, 5}, {120, 30, 4}}; int n = sizeof(items)/sizeof(items[0]); int W = 50; int maxVal = 0; knapsack(items, n, W, &maxVal); printf("Maximum value: %d", maxVal); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值