【usaco】Bessie's Secret Pasture 贝茜的秘密草坪

Bessie's Secret Pasture 贝茜的秘密草坪

这道题dp的转移的方式很妙,值得一记。

说实话,拿到这道题,我先想到的是一个5维的转移方程,不详细说,大概可以理解为我记录了各个重复物品的情况吧,毕竟最终方案是要考虑顺序的;我的目的是先跑多重背包,然后在答案处最后求组合数,然而实现太麻烦。

看了题解,我才感慨。

 

让我们直接看看状态枚举吧:

这是我们熟知的 01背包 的写法:先枚举物品,再枚举体积

而在此基础上的 多重背包 的写法:先枚举物品,接着是枚举放置物品个数,最后枚举体积

另外还有 记录已放物品数量的01背包 的写法:先枚举物品,接着是已放置物品个数,最后枚举体积 (最后两个好像可以调换)

而这道题则做出了美妙的变化:先枚举体积,再已放置物品个数,再枚举体积。 实际上这种做法放宽了转移,有意维护了选取物品顺序的随机

 

#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <bitset>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define INF (0x3f3f3f3f)
#define F(x, y, z) for(int x=y; x<=z; x++)
#define D(x, y, z) for(int x=z; x>=y; x--)
#define Mem(x, y) memset(x, (y), sizeof(x))
using namespace std;
#define N (10000)
#define L (500)
int n, n2, dp[N+L][5];
int main () 
{
    cin >> n; n2=sqrt(n);
    dp[0][0]=1; F(i, 1, n) F(j, 1, 4) for(int k=0; k*k<=i; k++) dp[i][j]+=dp[i-k*k][j-1];
    cout << dp[n][1]+dp[n][2]+dp[n][3]+dp[n][4];
    return 0; 
}

 

  

posted @ 2017-10-20 20:26  ToSoul  阅读(168)  评论(3编辑  收藏  举报