【动态规划】 洛谷 P1586 四方定理

159 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

【动态规划】 洛谷 P1586 四方定理

题目描述

四方定理是众所周知的:任意一个正整数n,可以分解为不超过四个整数的平方和。例如:25=12+22+22+4225=1^{2}+2^{2}+2^{2}+4^{2},当然还有其他的分解方案,25=42+3225=5225=4^{2}+3^{2}和25=5^{2}。给定的正整数n,编程统计它能分解的方案总数。注意:25=42+3225=32+4225=4^{2}+3^{2}和25=3^{2}+4^{2}视为一种方案。

输入格式

第一行为正整数t(t100)t(t\le 100),接下来t行,每行一个正整数n(n32768)n(n\le 32768)

输出格式

对于每个正整数n,输出方案总数。

样例 #1

样例输入 #1

 1
 2003

样例输出 #1

 48

解题思路:

这道题的做法有很多,而我要给大家介绍其中的两种做法:背包求解方案

先构造a[i],就是平方数,这是物品大小,n就是背包大小,设f[i]表示背包大小为i能装满的方案

核心如下:

 for (int i=1;i<=物品总数;i++)
        for (int j=a[i];j<=背包最高价值;j++)
           f[j]+=f[j-a[i]];

f[i][j]的第二维就是平方数的个数,在解决了方案总数怎么求之后,就要考虑只能用四个或四个以下。所以要加一维。

总结为fj代表价值上线为j,取k个数作组合时的方案总数。则最后答案为f[n][1]f[n][4]的和。

 #include<bits/stdc++.h>
 using namespace std;
 int a[200],f[32775][10],m,n;
 int main(){   
     for(int i=1;i<=181;i++)
     a[i]=i*i;             
     f[0][0]=1; 
     for (int i=1;i<=181;i++)
        for (int j=a[i];j<=32768;j++)
           for(int k=1;k<=4;k++)
           f[j][k]+=f[j-a[i]][k-1];
     cin>>n;
     for(int i=1;i<=n;i++){
         cin>>m;
         cout<<f[m][1]+f[m][2]+f[m][3]+f[m][4]<<endl;
     }
     return 0;
 }