【动态规划】【最短路】Codeforces 710E Generate a String

题目链接:

  http://codeforces.com/problemset/problem/710/E

题目大意:

  问写N个字符的最小花费,写一个字符或者删除一个字符花费A,将当前的字符数量翻倍花费B。

题目思路:

  【动态规划】【最短路】

  【动态规划】:

    如果当前x不是2的倍数,那么一定需要单个字符增加或删除,而这个单个操作越靠后答案越优。

     dp(x)=a+min(dp(x-1),dp(x+1))

    如果当前x是2的倍数,那么有两种情况,一种是通过翻倍的方式获得,一种是通过累加的方式获得。只要比较翻倍的代价和累加的代价。

    如果累加x/2次比翻倍更优,那么之前的x/2个一定是累加得到的(否则至少一次翻倍,而累加x/2次都比一次翻倍优)。

     dp(x)=(x/2*a<=b)?x*a:dp(x/2)+b;

  【最短路】(比赛的时候写的):

    f[x]表示生成x个字符的最小花费。f[x]可以扩展f[x-1],f[x+1],f[x+x]。

    加点小优化。不然会T。

    我就加了一个在f[x]+a



动态规划:

//
//by coolxxx
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-8)
#define J 10
#define mod 1000000007
#define MAX 0x7f7f7f7f
#define PI 3.14159265358979323
#define N 20000004
using namespace std;
typedef long long LL;
int cas,cass;
int n,m,lll,ans;
LL a,b;
LL dp(int x)
{
	if(x==0)return 0;
	if(x==1)return a;
	if(x&1)
	{
		LL x1=dp(x-1),x2=dp(x+1);
		return (LL)(a+min(x1,x2));
	}
	else if((LL)(x/2*a)<=b)return (LL)(x*a);
	else return (LL)(b+dp(x>>1));
}
int main()
{
	#ifndef ONLINE_JUDGE
//	freopen("1.txt","r",stdin);
//	freopen("2.txt","w",stdout);
	#endif
	int i,j,k;
//	for(scanf("%d",&cas);cas;cas--)
//	for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//	while(~scanf("%s",s+1))
	while(~scanf("%d",&n))
	{
		scanf("%I64d%I64d",&a,&b);
		printf("%I64d\n",dp(n));
	}
	return 0;
}
/*
//

//
*/



最短路:

//
//by coolxxx
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) ((a)*(a))
#define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define eps (1e-8)
#define J 10
#define mod 1000000007
#define MAX 0x7f7f7f7f
#define PI 3.14159265358979323
#define N 20000004
using namespace std;
typedef long long LL;
int cas,cass;
int n,m,lll,ans;
int q[N];
LL f[N];
LL a,b;
bool u[N];
void spfa()
{
	mem(f,14);mem(u,0);
	int i,x,l=0,r=1;
	f[1]=a;
	q[1]=1;
	for(r=2;r<=n;r++)
	{
		if(f[r-1]+a>b)break;
		q[r]=r;
		f[r]=f[r-1]+a;
	}
	while(l!=r)
	{
		x=q[l=(l+1)%N];
		u[x]=0;
		if(x<=n && f[x+x]>f[x]+b)
		{
			f[x+x]=f[x]+b;
			if(!u[x+x])
			{
				u[x+x]=1;
				q[r=(r+1)%N]=x+x;
			}
		}
		if(x>1 && f[x-1]>f[x]+a)
		{
			f[x-1]=f[x]+a;
			if(!u[x-1])
			{
				u[x-1]=1;
				q[r=(r+1)%N]=x-1;
			}
		}
		if(xf[x]+a)
		{
			f[x+1]=f[x]+a;
			if(!u[x+1])
			{
				u[x+1]=1;
				q[r=(r+1)%N]=x+1;
			}
		}
	}
}
int main()
{
	#ifndef ONLINE_JUDGE
//	freopen("1.txt","r",stdin);
//	freopen("2.txt","w",stdout);
	#endif
	int i,j,k;
//	for(scanf("%d",&cas);cas;cas--)
//	for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
//	while(~scanf("%s",s+1))
	while(~scanf("%d",&n))
	{
		scanf("%I64d%I64d",&a,&b);
		spfa();
		printf("%I64d\n",f[n]);
	}
	return 0;
}
/*
//

//
*/


你可能感兴趣的:(Codeforces,题解,图论—最短路)