动态规划

动态规划弱渣决定开始补脑

ZOJ2402 类似于最长递增子序列

f(n, m) = f(n-1, m/2) + f(n-1, (m-1)/2) +...... + f(n-1, 1)
f[1][i]=i

#include<iostream>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
//f(n, m) = f(n-1, m/2) + f(n-1, (m-1)/2) +...... + f(n-1, 1)  
//f[1][i]=i  
long long f[11][2001];  
int main()  
{  
    int n,m,i,j,k;  
    int t;  
    memset(f,0,sizeof(f));  
    for(i=1;i<2001;i++)f[1][i]=i;  
    for(i=2;i<11;i++)  
    {  
        for(j=2;j<2001;j++)  
        {  
            for(k=j;k>1;k--)  
            {  
                f[i][j]+=f[i-1][k/2];  
            }  
        }  
    }  
    cin>>t;  
    int ca=1;  
    while(t--)  
    {  
        cin>>n>>m;  
        printf("Case %d: n = %d, m = %d, # lists = %lld\n",ca++,n,m,f[n][m]);  
    }  
    return 0;  
}  


ZOJ2401简单的dp

注意边界

dp[i][j]表示a的前i个与b的前j个是否能构成c的前i+j个

#include<cmath>  
#include<iostream>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
#define N 220  
int main()  
{  
    bool dp[N][N];  
    char a[N],b[N],c[2*N];  
    int t,i,j;  
    int k=1;  
    cin>>t;  
    while(t--)  
    {  
        scanf("%s%s%s",a,b,c);  
        int lena=strlen(a);  
        int lenb=strlen(b);  
        memset(dp,0,sizeof(dp));  
        dp[0][0]=1;  
        for(i=0;i<=lena;i++)//注意边界当a用完时dp[i][j] i=lena  
        {  
            for(j=0;j<=lenb;j++)  
            {  
  
                if(dp[i][j])  
                {  
                    if(a[i]==c[i+j])dp[i+1][j]=1;  
                    if(b[j]==c[i+j])dp[i][j+1]=1;  
                }  
            }  
  
        }  
        printf("Data set %d: ",k++);  
        if(dp[lena][lenb])printf("yes\n");  
        else printf("no\n");  
    }  
    return 0;  
}  





CF267

C. George and Job
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn't have enough money, so George was going to work as a programmer. Now he faced the following problem at the work.

Given a sequence of n integers p1, p2, ..., pn. You are to choose k pairs of integers:

[l1, r1], [l2, r2], ..., [lk, rk] (1 ≤ l1 ≤ r1 < l2 ≤ r2 < ... < lk ≤ rk ≤ nri - li + 1 = m), 

in such a way that the value of sum  is maximal possible. Help George to cope with the task.

Input

The first line contains three integers nm and k (1 ≤ (m × k) ≤ n ≤ 5000). The second line contains n integers p1, p2, ..., pn (0 ≤ pi ≤ 109).

Output

Print an integer in a single line — the maximum possible value of sum.

Sample test(s)
input
5 2 1
1 2 3 4 5
output
9
input
7 1 3
2 10 7 18 5 33 0
output
61

dp[i][j] 表示在前j个选i对的最大值

s[i] 是前缀和

dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+s[j]-s[j-m]);

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 5005
__int64 dp[N][N];
__int64 a[N],s[N];
int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=1;i<=n;i++)scanf("%d",&s[i]),s[i]+=s[i-1];
        for(int i=1;i<=k;i++)
        {
            for(int j=i*m;j<=n;j++)
            {
                dp[i][j]=max(dp[i][j-1],dp[i-1][j-m]+s[j]-s[j-m]);
                //printf("i= %d j=%d ,%d\n",i,j,dp[i][j]);
            }
        }
        printf("%I64d\n",dp[k][n]);
    }
    return 0;
}

/*
7 2 3
2 10 7 18 5 33 6

*/


1007. Maximum Subsequence Sum (25)

时间限制
400 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, Ni+1, ..., Nj } where 1 <= i <= j <= K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (<= 10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21
Sample Output:
10 1 4
同HDU1003 dp[i]=max(a[i],dp[i-1]+a[i]);

#include<iostream>
#include<cstdio>
using namespace std;
int dp[10010];
int main()
{
    int T,n,i,t,a[10010],st,stop,max,j;
    while(~scanf("%d",&n)){

        scanf("%d",&a[1]);
        dp[1]=a[1];
        stop=1;j=1;
        st=1;
        max=dp[1];
        for(i=2;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>dp[i-1]+a[i]){
                dp[i]=a[i];
                st=i;
            }
            else dp[i]=dp[i-1]+a[i];
            if(max<dp[i]){
                max=dp[i];
                stop=st;
                j=i;
            }
        }
      //  printf("Case %d:\n",t);
        if(max<0)printf("0 %d %d\n",a[1],a[n]);
        else printf("%d %d %d\n",max,a[stop],a[j]);
        if(T>0)printf("\n");
    }
    return 0;
}//test: 3    1 -9  3 -1 10 -2    3 -2 10 -1


1033. To Fill or Not to Fill (25)

时间限制
10 ms
内存限制
32000 kB
代码长度限制
16000 B
判题程序
Standard
作者
ZHANG, Guochuan

With highways available, driving a car from Hangzhou to any other city is easy. But since the tank capacity of a car is limited, we have to find gas stations on the way from time to time. Different gas station may give different price. You are asked to carefully design the cheapest route to go.

Input Specification:

Each input file contains one test case. For each case, the first line contains 4 positive numbers: Cmax (<= 100), the maximum capacity of the tank; D (<=30000), the distance between Hangzhou and the destination city; Davg (<=20), the average distance per unit gas that the car can run; and N (<= 500), the total number of gas stations. Then N lines follow, each contains a pair of non-negative numbers: Pi, the unit gas price, and Di (<=D), the distance between this station and Hangzhou, for i=1,...N. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the cheapest price in a line, accurate up to 2 decimal places. It is assumed that the tank is empty at the beginning. If it is impossible to reach the destination, print "The maximum travel distance = X" where X is the maximum possible distance the car can run, accurate up to 2 decimal places.

Sample Input 1:
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300
Sample Output 1:
749.17
Sample Input 2:
50 1300 12 2
7.10 0
7.00 600
Sample Output 2:
The maximum travel distance = 1200.00
一开始用dp没过

后来才想到经过加油站油量是可以有剩余的,只要使每段路的油费尽量小就可以了,贪心解决

dp代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<map>
#define N 550
#define INF 0x7fffffff
using namespace std;
int num;
double destination,capacity,disavg;
double dp[N];
struct ss
{
    double price;
    double dis;
}a[N];
double dis[N];
bool cmp(ss a,ss b)
{
    return a.dis<b.dis;
}
int main()
{
    while(~scanf("%lf%lf%lf%d",&capacity,&destination,&disavg,&num))
    {
        int i,j;
        for(i=0;i<num;i++)
        {
            scanf("%lf%lf",&a[i].price,&a[i].dis);
        }
        a[num].dis=destination;
        a[num].price=1000000000000;
        sort(a,a+num+1,cmp);
        for(i=0;i<=num;i++)dis[i]=a[i].dis;
        for(i=0;i<=num;i++)dp[i]=INF;

        for(i=0;i<=num;i++)
        {
           // printf("-- %d %lf %lf\n",i,a[i].dis,a[i].price);
        }
        if(abs(a[0].dis)>0.0000001){
            printf("The maximum travel distance = 0.00\n");
            continue;
        }
        double MAX_dis=capacity*disavg;
        dp[0]=0;
        for(i=1;i<=num;i++)
        {
            if(a[i].dis-a[i-1].dis>MAX_dis)break;
            j=lower_bound(dis,dis+num,a[i].dis-MAX_dis)-dis;
          //  printf("-- %d %d \n",i,j);
            for(;j<i;j++)
            {
                dp[i]=min(dp[i],dp[j]+(a[i].dis-a[j].dis)*a[j].price/disavg);
            //    printf("%d %lf\n",j,dp[i]);
            }
        }
        if(i<=num)
            printf("The maximum travel distance = %.2lf\n",a[i-1].dis+MAX_dis);
        else printf("%.2lf\n",dp[num]);
    }
    return 0;
}
/*
50 1300 12 8
6.00 1250
7.00 600
7.00 150
7.10 0
7.20 200
7.50 400
7.30 1000
6.85 300

*/

贪心代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<cmath>
#include<map>
#define N 550
#define INF 0x7fffffff
using namespace std;
int n;
double destination,capacity,disavg;
double node[N*2];
double MAX_dis;
struct ss
{
    double price;
    double dis;
}a[N];
bool cmp(ss a,ss b)
{
    return a.dis<b.dis;
}
struct sss
{
    double a,b,cost;
}point[N*2];
int main()
{
    while(~scanf("%lf%lf%lf%d",&capacity,&destination,&disavg,&n))
    {
        MAX_dis=capacity*disavg;
        int i,j,k=0;
        for(i=0;i<n;i++)
        {
            scanf("%lf%lf",&a[i].price,&a[i].dis);
            if(a[i].dis<destination)node[k++]=a[i].dis;
            if(a[i].dis+MAX_dis<destination)node[k++]=a[i].dis+MAX_dis;
        }
        a[n].dis=destination;
        sort(a,a+n+1,cmp);
        if(abs(a[0].dis)>0.0000001){  
            printf("The maximum travel distance = 0.00\n");  
            continue;  
        }  
        for(i=1;i<=n;i++){
            if(a[i].dis-a[i-1].dis>MAX_dis)break;
        }
        if(i<=n){
            printf("The maximum travel distance = %.2lf\n",a[i-1].dis+MAX_dis);
            continue;
        }

        node[k++]=destination;
        sort(node,node+k);
        int kk=0;
        for(i=1;i<k;i++)
        {
            if(node[i]!=node[i-1])
            {
                point[kk].a=node[i-1];
                point[kk].b=node[i];
                point[kk++].cost=INF;
            }
        }
        for(i=0;i<kk;i++)
        {
           // printf("// %lf %lf %lf\n",point[i].a,point[i].b,point[i].cost);
        }
        for(i=0;i<n;i++)
        {
            for(j=0;j<kk;j++)
            {
                if(point[j].a>=a[i].dis&&point[j].b<=a[i].dis+MAX_dis)
                {
                    if(a[i].price<point[j].cost)point[j].cost=a[i].price;
                }
            }
        }
        for(i=0;i<kk;i++)
        {
          //  printf("//** %lf %lf %lf\n",point[i].a,point[i].b,point[i].cost);
        }
        double ans=0;
        for(i=0;i<kk;i++)
        {
            ans+=(point[i].b-point[i].a)/disavg*point[i].cost;
        }
        printf("%.2lf\n",ans);

    }
    return 0;
}

ZOJ3725 DP解排列计数

题目链接:Click here~~

题意:

n个格子排成一条直线,可以选择涂成红色或蓝色,问最少 m 个连续为红色的方案数。

解题思路:

应该是这次 ZOJ 月赛最水的一题,可惜还是没想到。。。

dp[i] 表示前 i 个最少 m 个连续为红色的方案数。

转移时,分类讨论:

1、前 i-1 个已经满足这个性质,那么,第 i 个随意涂色,方案数为 dp[i-1] * 2 。

2、前 i-1 个不满足这个性质,那么,要想成为方案,区间 [i-m+1,i] 必须涂成红色。并且,下标为 i-m 这个点必须是蓝色,否则就与 情况1 重复了。

而且正是由于这一点,只要剩下的区间 [1,i-m-1] 不满足这个性质,就能保证整个区间 [1,i-1] 不满足这个性质。方案数为 2^(i-m-1) - dp[i-m-1]。

#include<iostream>  
#include<cstdio>  
#include<vector>  
#include<cstring>  
using namespace std;  
const int N=1e5+5;  
const int mod=1e9+7;  
int dp[N],pow[N]={1};  
int main()  
{  
    int n,m,i;  
    for(i=1;i<N;i++)pow[i]=pow[i-1]*2%mod;  
    while(~scanf("%d%d",&n,&m))  
    {  
        memset(dp,0,sizeof(dp));  
        dp[m]=1;  
        for(i=m+1;i<=n;i++)dp[i]=(dp[i-1]*2%mod+(pow[i-m-1]-dp[i-m-1]+mod)%mod)%mod;  
        printf("%d\n",dp[n]);  
    }  
    return 0;  
}  







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值