Jzoj P5907 轻功___动态规划

题目大意:

给出一个长为 N N N的序列,起点在 0 0 0,有 K K K种方式,每种可以花费 w i w_i wi然后从某个位置 i i i走到位置 i + C i i+C_i i+Ci,如果走到 i i i用的是 j j j方式,那么当你下一次走的时候方式不是 j j j时,切换方式需要花费 W W W,有 Q Q Q个限制 a i , b i a_i,b_i ai,bi,表示不能使用方式 a i a_i ai经过位置 b i b_i bi,问走到位置 N N N的最少花费。

N < = 500 , K < = 100 N<=500,K<=100 N<=500K<=100
Q < = 50000 , W < = 1 e 7 Q<=50000,W<=1e7 Q<=50000W<=1e7

分析:

f [ i ] [ j ] f[i][j] f[i][j]表示走到位置 i i i时方式为 j j j的最少花费,
f [ i ] [ j ] = m i n ( f [ i − C k ] [ k ] + w i + ( ( k = j ) ? 0 : W ) ) f[i][j]=min(f[i-C_k][k]+w_i+((k=j)? 0:W)) f[i][j]=min(f[iCk][k]+wi+((k=j)?0:W))
时间复杂度: O ( N K 2 ) O(NK^2) O(NK2)

代码:

#include 
#include 
#include 
#include 
#include 
#include 
#define inf 0x7fffffff
#define N 505
#define M 105

using namespace std;

typedef long long ll;

struct Node { int len; ll cost; }a[M];
int sum[M][N], n, m, Q;
ll f[N][N], W;

int read(int &x)
{
	int f = 1; x = 0; char s = getchar();
	while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
	while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
	x = x * f;
}

void write(ll x)
{
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int main()
{
    freopen("qinggong.in", "r", stdin);
    freopen("qinggong.out", "w", stdout);
	read(n); read(m); ++n; scanf("%lld", &W);
    for (int i = 1; i <= m; i++) read(a[i].len), scanf("%lld", &a[i].cost);
    read(Q);
    while (Q--)
    {
           int x, y; read(x); read(y);
           sum[y][x + 1] = 1;
	}
	for (int i = 1; i <= m; i++) 
	     for (int j = 1; j <= n; j++) sum[i][j] = sum[i][j] + sum[i][j - 1];	
	for (int i = 2; i <= n; i++) 
	     for (int j = 1; j <= m; j++) f[i][j] = inf;
	     
	for (int i = 2; i <= n; i++)
		 for (int j = 1; j <= m; j++)
		      if (i > a[j].len)
	              if (sum[j][i] - sum[j][i - a[j].len - 1] == 0)
	              {
	          	      for (int k = 1; k <= m; k++)
				            if (k != j) f[i][j] = min(f[i][j], f[i - a[j].len][k] + W + a[j].cost);
					               else f[i][j] = min(f[i][j], f[i - a[j].len][k] + a[j].cost);	
				  }
		  
	ll ans = inf;
	for (int i = 1; i <= m; i++) ans = min(ans, f[n][i]);
	if (ans == inf) printf("-1\n");
	         else { write(ans); printf("\n"); }
	return 0;	
} 

你可能感兴趣的:(C++,动态规划)