ural 1073. Square Country

1073. Square Country

Time Limit: 1.0 second
Memory Limit: 64 MB
There live square people in a square country. Everything in this country is square also. Thus, the Square Parliament has passed a law about a land. According to the law each citizen of the country has a right to buy land. A land is sold in squares, surely. Moreover, a length of a square side must be a positive integer amount of meters. Buying a square of land with a side a one pays a2 quadrics (a local currency) and gets a square certificate of a landowner.
One citizen of the country has decided to invest all of his N quadrics into the land. He can, surely, do it, buying square pieces 1 × 1 meters. At the same time the citizen has requested to minimize an amount of pieces he buys: "It will be easier for me to pay taxes," — he has said. He has bought the land successfully.
Your task is to find out a number of certificates he has gotten.

Input

The only line contains a positive integer N ≤ 60 000 , that is a number of quadrics that the citizen has invested.

Output

The only line contains a number of certificates that he has gotten.

Sample

inputoutput
344
3
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define MAX 60000+1
 6 using namespace std;
 7 int dp[MAX] ;
 8 int main(){
 9     int n;
10     cin >> n;
11     fill(dp,dp+MAX,1<<30);
12     dp[0] = 0;
13     for(int i = 1; i <=(int)sqrt(n); i ++ ){
14         for(int j = i*i; j <= n; j ++ ){
15             dp[j] = min(dp[j],dp[j-i*i]+1);
16         }
17     }
18     cout<<dp[n]<<endl;
19     return 0;
20 }

 //回溯法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define MAX 250
using namespace std;
int minnum = 1<<30;

bool BackTrack(int num,int n){
    if(n == 0) minnum = min(num,minnum);
    else{
        int node[250],len,k;
        for(len = 0,k = (int)sqrt(n); k > 0; k--,len++) node[len]=k;
        for(int i = 0; i < len; i ++ )
            if(num + 1 < minnum){
                if(!BackTrack(num+1,n - node[i]*node[i])) return true;
            }
            else return false;
    }
    return true;
}

int main(){
    int n;
    cin >> n;
    BackTrack(0,n);
    cout<<minnum<<endl;
    return 0;
}

 对两种回溯进行测试,但下面这种回溯会超时,不知道为什么,求解答

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define MAX 250
using namespace std;
int minnum = 1<<30;
void BackTrack(int num,int n){
    if(num >= minnum) return;
    if(n == 0) minnum = min(num,minnum);
    else{
        int node[250],len,k;
        for(len = 0,k = (int)sqrt(n); k > 0; k--,len++) node[len]=k;
        for(int i = 0; i < len; i ++ ) BackTrack(num+1,n - node[i]*node[i]);
    }
}

int main(){
    int n;
    cin >> n;
    BackTrack(0,n);
    cout<<minnum<<endl;
    return 0;
}

测试代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define MAX 250
using namespace std;
int minnum = 1<<30;
int minnum1 = 1<<30;
void BackTrack(int num,int n){
    if(num >= minnum) return;
    if(n == 0) minnum = min(num,minnum);
    else{
        int node[250],len,k;
        for(len = 0,k = (int)sqrt(n); k > 0; k--,len++) node[len]=k;
        for(int i = 0; i < len; i ++ ) BackTrack(num+1,n - node[i]*node[i]);
    }
}
bool BackTrack1(int num,int n){
    if(n == 0) minnum1 = min(num,minnum1);
    else{
        int node[250],len,k;
        for(len = 0,k = (int)sqrt(n); k > 0; k--,len++) node[len]=k;
        for(int i = 0; i < len; i ++ )
            if(num + 1 < minnum1){
                if(!BackTrack1(num+1,n - node[i]*node[i])) return true;
            }
            else return false;
    }
    return true;
}
int main(){
    int n;
    for(int n =1; n<= 60000; n ++ ){
        BackTrack(0,n);
        BackTrack1(0,n);
        if(minnum != minnum1){cout<<n<<" error"<<endl;break;}
    }
    return 0;
}



原文地址:https://www.cnblogs.com/xiongqiangcs/p/3034894.html