您的位置:首页 > 其它

USACO 4.3.1 Buy Low, Buy Lower

2014-04-10 05:00 411 查看
线性DP, 笨得WA了10次才AC,而且高精度加法还是借用的别人的,自己的压位高精度大数算的好奇怪。。。
本题的重点在于第二问的判重。可以证明,对于相同price的i, j(i<j),应该选择j,因为j包含i的所有情况。
那么怎么判断某个price是待计算的i前面的最后一个那个j呢,这里我实在太挫没有思路。
后来参考了别人的做法,我们可以给每一个j构造一个next指针指向下一个相同数字的下标,如果这个下标>i那么就表明j是最后一个。
然后就很简单了,把所有的最后一个加起来就行了。不过本题要使用高精度算法,总时间复杂度为O(N2)。

Compile: OK

Executing...
Test 1: TEST OK [0.011 secs, 5896 KB]
Test 2: TEST OK [0.011 secs, 5896 KB]
Test 3: TEST OK [0.011 secs, 5896 KB]
Test 4: TEST OK [0.011 secs, 5896 KB]
Test 5: TEST OK [0.011 secs, 5896 KB]
Test 6: TEST OK [0.022 secs, 5896 KB]
Test 7: TEST OK [0.032 secs, 5896 KB]
Test 8: TEST OK [0.011 secs, 5896 KB]
Test 9: TEST OK [0.065 secs, 5896 KB]
Test 10: TEST OK [0.248 secs, 5896 KB]

All tests OK.

Your program ('buylow') produced all correct answers! This is your submission #11 for this problem. Congratulations!

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
using namespace std;

int N, price[5001];
int eqn[5001];

int dp[5001];

struct bign
{
char n[500];
int len;
bign():len(1)
{
memset(n,0,sizeof(n));
}
void operator = (const int v)
{
len = 1;
n[0] = v;
}

void operator += (const bign &rhs)
{
if(rhs.len>len)
len=rhs.len;
for(int i=0;i<len;++i)
{
n[i]+=rhs.n[i];
if(n[i]>9)
{
++n[i+1];
n[i]-=10;
}
}
if(n[len])
++len;
}
void print()
{
for(int i=len-1;i>=0;--i)
cout << (int)n[i];
}
}dp2[5001];

int main(void)
{
freopen("buylow.in", "r", stdin);
freopen("buylow.out", "w", stdout);
int i, m;

cin >> N;
for(i=0; i<N; ++i) cin >> price[i];
N++;    // 增加一个超级节点, price[supernode] = 0;

for(i=0; i<N-1; ++i) {
int j;
for(j=i+1; j<N; ++j)
if (price[j] == price[i]) {
eqn[i] = j;
break;
}
if (j >= N) eqn[i] = N;
}
eqn[N-1] = N;

for(i=0; i<N; ++i) {
dp[i] = 1;
dp2[i] = 1;
int j;
for(j=0; j<i; ++j) {
if (price[i] < price[j]) {
if (eqn[j] > i) {
const int k = dp[j] + 1;
if (k > dp[i]) {
dp[i] = k;
dp2[i] = dp2[j];
} else if (k == dp[i])
dp2[i] += dp2[j];
}
}
}
}
cout << dp[N-1] - 1 << ' ';
dp2[N-1].print();
cout << endl;

return 0;
}


2014/5/20更新:

终于用上自己的高精度了,效率貌似还可以。

Compiling...
Compile: OK

Executing...
Test 1: TEST OK [0.008 secs, 5400 KB]
Test 2: TEST OK [0.011 secs, 5400 KB]
Test 3: TEST OK [0.008 secs, 5400 KB]
Test 4: TEST OK [0.008 secs, 5400 KB]
Test 5: TEST OK [0.014 secs, 5400 KB]
Test 6: TEST OK [0.024 secs, 5400 KB]
Test 7: TEST OK [0.022 secs, 5400 KB]
Test 8: TEST OK [0.024 secs, 5400 KB]
Test 9: TEST OK [0.054 secs, 5400 KB]
Test 10: TEST OK [0.270 secs, 5400 KB]

All tests OK.

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
using namespace std;

int N, price[5001];
int eqn[5001];

int dp[5001];

#define min(a,b)    ((a)>(b)?(b):(a))
#define max(a,b)    ((a)>(b)?(a):(b))

#define BIGNUM_LL            100
#define BIGNUM_BL            "4"
#define BIGNUM_MOD            10000UL
typedef typeof(BIGNUM_MOD) bignum_block;

struct bignum {
unsigned len;
bignum_block blks[BIGNUM_LL];

bignum() {blks[0]=0, len=1;}

bignum(unsigned num) {
len = 0;
while(num) {
blks[len++] = num % BIGNUM_MOD;
num /= BIGNUM_MOD;
}
}

void operator += (bignum &b) {
int i;
bignum_block carry;

i = len; do blks[i++] = 0; while(i<=b.len);

carry = i = 0;
for(; i<b.len; ++i) {
blks[i] += b.blks[i];
blks[i+1] += blks[i] / BIGNUM_MOD;
blks[i] %= BIGNUM_MOD;
}
for(; i<len; ++i) {
blks[i+1] +=  blks[i] / BIGNUM_MOD;
blks[i] %= BIGNUM_MOD;
}
len = i + (blks[i] > 0);
}

void print() {
printf("%d", blks[len-1]);
for(int i=len-1; i--; )
printf("%0" BIGNUM_BL "d", blks[i]);
}
}dp2[5001];

int main(void)
{
freopen("buylow.in", "r", stdin);
freopen("buylow.out", "w", stdout);
int i, m;

cin >> N;
for(i=0; i<N; ++i) cin >> price[i];
N++;    // 增加一个超级节点, price[supernode] = 0;

for(i=0; i<N-1; ++i) {
int j;
for(j=i+1; j<N; ++j)
if (price[j] == price[i]) {
eqn[i] = j;
break;
}
if (j >= N) eqn[i] = N;
}
eqn[N-1] = N;

for(i=0; i<N; ++i) {
dp[i] = 1;
dp2[i] = 1;
int j;
for(j=0; j<i; ++j) {
if (price[i] < price[j]) {
if (eqn[j] > i) {
const int k = dp[j] + 1;
if (k > dp[i]) {
dp[i] = k;
dp2[i] = dp2[j];
} else if (k == dp[i])
dp2[i] += dp2[j];
}
}
}
}
cout << dp[N-1] - 1 << ' ';
dp2[N-1].print();
cout << endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: