这题是让你从0得到n,+1−1花费是x,∗2花费是y
首先想到bfs,类似spfa那样更新,但是会T,要加个剪枝就是u−>2u的时候,花费应该是取min(y,x∗u),2u≥n的时候,可以直接更新n的结果,然后继续bfs
dp的方法是,考虑x,他可能是来自x−1,也可能是后面来的
x为奇数,dp[i]=min(dp[i−1]+x,dp[(i+1)/2]+x+y)
因为,如果从后面来,那么肯定是通过翻倍过来的,至于翻倍到哪里,如果是翻倍到i+3,那么就要三次x的花费,直接他在没翻倍前−1,就能少做一次x,所以是这样转移
x是偶数的时候,dp[i]=min(dp[i−1]+x,dp[i/2]+y)
理由同上
代码1:
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <queue>
#include <cmath>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 10000005
#define MAXN 1000005
#define maxnode 205
#define sigma_size 26
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-4;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
LL dp[MAX];
int vis[MAX];
int main(){
int n;
LL x,y;
while(cin>>n>>x>>y){
for(int i=1;i<=n;i++) dp[i]=1e18;
mem(vis,0);
queue<int> q;
dp[1]=x;
q.push(1);
vis[1]=1;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
if(u-1>0&&dp[u-1]>dp[u]+x){
dp[u-1]=dp[u]+x;
if(!vis[u-1]){
q.push(u-1);
vis[u-1]=1;
}
}
if(u+1<=n&&dp[u+1]>dp[u]+x){
dp[u+1]=dp[u]+x;
if(!vis[u+1]){
q.push(u+1);
vis[u+1]=1;
}
}
LL cost=min(y,x*u);
if(2*u<=n&&dp[2*u]>dp[u]+cost){
dp[2*u]=dp[u]+cost;
if(!vis[2*u]){
q.push(2*u);
vis[2*u]=1;
}
}
if(2*u>n&&dp[n]>dp[u]+y+(2*u-n)*x){
dp[n]=dp[u]+y+(2*u-n)*x;
if(!vis[n]){
vis[n]=1;
q.push(n);
}
}
}
cout<<dp[n]<<endl;
}
return 0;
}
代码2:
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <queue>
#include <cmath>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define MAX 10000005
#define MAXN 1000005
#define maxnode 205
#define sigma_size 26
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lrt rt<<1
#define rrt rt<<1|1
#define middle int m=(r+l)>>1
#define LL long long
#define ull unsigned long long
#define mem(x,v) memset(x,v,sizeof(x))
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define bits(a) __builtin_popcount(a)
#define mk make_pair
#define limit 10000
//const int prime = 999983;
const int INF = 0x3f3f3f3f;
const LL INFF = 0x3f3f;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-4;
const LL mod = 1e9+7;
const ull mx = 133333331;
/*****************************************************/
inline void RI(int &x) {
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/
LL dp[MAX];
int main(){
int n;
LL x,y;
while(cin>>n>>x>>y){
dp[0]=0;
for(int i=1;i<=n;i++){
dp[i]=1e18;
if(i&1){
dp[i]=min(dp[i-1]+x,dp[(i+1)/2]+x+y);
}
else dp[i]=min(dp[i-1]+x,dp[i/2]+y);
//cout<<dp[i]<<endl;
}
cout<<dp[n]<<endl;
}
return 0;
}