您的位置:首页 > 其它

BZOJ1111: [POI2007]四进制的天平Wag

2017-09-26 16:28 344 查看
我们先把n转4进制

然后这题有几个性质:

使用的砝码最大幂次不超过n的最高位+1

每一位如果接受高位的退位,接受的次数不超过1次

然后就可以根据这个dp了

从低位往高位dp

f[i]表示第i位不接受高位的退位,1~i最少需要的砝码数

g[i]表示第i位接受高位的退位,1~i最少需要的砝码数



f[i]=min(f[i−1]+a[i],g[i−1]+a[i]+1)

g[i]=min(f[i−1]+4−a[i],g[i−1]+3−a[i])

顺便dp方案数

code:

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e9
using namespace std;

const int maxn = 2100;
const ll Mod = 1e9;

int len;
char str[maxn];
int s1[maxn],s2[maxn];
int a[maxn],tp;

ll f[maxn],fn[maxn],g[maxn],gn[maxn];

int main()
{
scanf("%s",str); len=strlen(str);
for(int i=0;i<len;i++) s1[i]=str[i]-'0';
int pos=0;
while(pos<len)
{
int now=0;
for(int j=pos;j<len;j++)
{
now=now*10+s1[j];
s2[j]=now>>2; now&=3;
}
a[++tp]=now;
for(int i=0;i<len;i++) s1[i]=s2[i];
while(pos<len&&!s1[pos]) pos++;
}
++tp;
f[0]=0,fn[0]=1; g[0]=inf,gn[0]=0;
for(int i=1;i<=tp;i++)
{
int temp;

f[i]=f[i-1]+a[i],fn[i]=fn[i-1];
temp=g[i-1]+a[i]+1;
if(temp<f[i]) f[i]=temp,fn[i]=gn[i-1];
else if(temp==f[i]) (fn[i]+=gn[i-1])%=Mod;

g[i]=f[i-1]+4-a[i]; gn[i]=fn[i-1];
temp=g[i-1]+3-a[i];
if(temp<g[i]) g[i]=temp,gn[i]=gn[i-1];
else if(temp==g[i]) (gn[i]+=gn[i-1])%=Mod;
}
printf("%lld\n",fn[tp]);

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