动态规划例题之线性模型

1. POJ 3616 Milking Time

题目链接:

http://poj.org/problem?id=3616

先按时间先后顺序排序,然后按照题目所要求的规则进行dp。

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
struct node
{
    int st,en,eff;
};
int n,m,r;
node a[maxn];
int dp[maxn];
int compare (node a ,node b)
{
    if(a.st!=b.st) return a.st<b.st;
    return a.en<b.en;
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&r)!=EOF)
    {
        int ans=0;
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a[i].st,&a[i].en,&a[i].eff);
        }
        a[0].st=a[0].en=a[0].eff=0;
        sort (a+1,a+m+1,compare);
        memset (dp,0,sizeof(dp));
        for (int i=1;i<=m;i++) dp[i]=a[i].eff;
        for (int i=1;i<=m;i++)
        {
            for (int j=1;j<i;j++)
            {
                if(a[i].st<a[j].en+r) continue;
                dp[i]=max(dp[i],dp[j]+a[i].eff);
                ans=max(dp[i],ans);
            }
        }
        printf("%d\n",ans);
    }
	return 0;
}

2. POJ 3486 Computers

题目链接:

http://poj.org/problem?id=3486

思路:

设dp[i]表示为第i天的最小花费,则有dp[i]=min(dp[i],dp[j]+c+a[j+1][i])(0<j<i);

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int c;
int n;
int a[maxn][maxn];
int dp[maxn];
int main()
{
    while(scanf("%d",&c)!=EOF)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            for (int j=i;j<=n;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        dp[0]=0;
        for (int i=1;i<=n;i++) dp[i]=INF;
        int ans=INF;
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<n;j++)
            {
                dp[i]=min(dp[i],dp[j]+a[j+1][i]+c);
            }
        }
        printf("%d\n",dp[n]);
    }
	return 0;
}

3. POJ 3404 Bridge over a rough river

题目链接:

http://poj.org/problem?id=3404

思路:

仅仅是贪心第一个与其他的人一起走的想法是不对的,比如1 2 5 10,1,2现在,然后1回来,之后5,10走,2回来,然后1,2这样就不符合贪心思想。

此题可以通过动态规划来做。

因为存在上面所述的状态转移情况,所以递推式为:

dp[i]=min(dp[i-1]+a[1]+a[i],dp[i-2]+a[1]+a[i]+2*a[2]);

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
const int maxn = 50+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int n;
int a[maxn];
int dp[maxn];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        dp[0]=0;
        dp[1]=a[1];
        dp[2]=a[2];
        for (int i=3;i<=n;i++)
        {
            dp[i]=min(dp[i-1]+a[1]+a[i],dp[i-2]+a[1]+a[i]+2*a[2]);
        }
        printf("%d\n",dp[n]);
    }
	return 0;
}

4. POJ 1700 Crossing River

题目链接:

http://poj.org/problem?id=1700

此题只是在上一题的基础上加大了数据规模

代码如下:

//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 1000000007;
const int maxn = 1050+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
	char c; int sgn;
	if (c = getchar(), c == EOF) return 0;
	while (c != '-' && (c<'0' || c>'9')) c = getchar();
	sgn = (c == '-') ? -1 : 1;
	ret = (c == '-') ? 0 : (c - '0');
	while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
	ret *= sgn;
	return 1;
}
int t;
int n;
int a[maxn];
int dp[maxn];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        dp[0]=0;
        dp[1]=a[1];
        dp[2]=a[2];
        for (int i=3;i<=n;i++)
        {
            dp[i]=min(dp[i-1]+a[1]+a[i],dp[i-2]+a[1]+a[i]+2*a[2]);
        }
        printf("%d\n",dp[n]);
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89464052