小白进阶之路-FZU - 1695-DP

题目:

简单错误思路:

  dfs:每个状态都需要遍历,所以最坏2 ^ 50 ,TLE

  类似于01滚动:考虑到空间存不下就没有实际行动,大概率 MLE

正确答案:

  类似于第二种状态,不过是状态压缩,原地滚动,每一步都利用上一步的结果,且用0,1表示状态,节省空间,然后扫一遍判断答案数量即可。 

思考:DP真香

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<stack>
#include<queue>
#include<map> 
#include<list>
#include<string>
#include<ctype.h>
#include<cstring>
#include<set>
#include<vector>
#define ll long long
#define mp make_pair 
#define inf 0x3f3f3f3f
#define pb push_back
#define PI 3.14159265358979323846
using namespace std;
const int maxn = 5e4 + 100;
void Fast()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
}

int p[maxn] = {0};



int main()
{
    p[0] = p[1] = 1;
    for(int i = 2;i < maxn;i++){ // 埃氏筛素数
        if(!p[i]){
            for(int j = i + i ; j < maxn;j += i) p[j] = 1;
        }
    }

    int n;
    while(~scanf("%d",&n)){
        if(n < 0) break;
        int a[2020];int dp[maxn] = {0}; // dp[i] = 0 表示不能等于 i ,dp[i] = 1 表示可以等于 i
        int sum = 0;
        for(int i = 1 ;i <= n;i++) {
            scanf("%d",&a[i]);
            sum += a[i];
        }
        dp[0] = 1;
        for(int i = 1; i <= n;i++){ // 原地滚动DP,我其实没有特别理解,在雨巨的视频里听过
            for(int j = sum - a[i];j >= 0;j--){
                if(dp[j]) dp[j+a[i]] = 1;
            }
        }
        int ans = 0;
        for(int i = 2;i <= sum;i++){
            if(dp[i] == 1 && p[i] == 0) ans++;
        }
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/Wise-XiaoWei4/p/12918901.html