您的位置:首页 > 其它

DP专题考试总结(4)

2017-10-02 17:35 127 查看
最近努力学(tui)习(fei)了DP专题,然后考试又挂了,然后就没有然后了。

对此,我只想说——

吾每念,常痛于骨髓,顾计不知所出耳!

广场铺砖问题

期望得分:40

实际得分:10

Description

有一个 W行 H列的广场,需要用 1*2小砖铺盖,小砖之间互相不能重叠,问

有多少种不同的铺法?

Date Size

1<=W,H<=11

Solution

这是一道状压DP中的水题。我难道会告诉你我跳了状态压缩DP吗

于是乎,自顾自的打了40分的暴力走人。

可以按行枚举,有三种选择:①空着②摆一个横的③摆一个占用上一行的竖的

但第一行没有③选项,那么就把第一行处理成全摆满的情况。

然后开始愉快地状态DP。

Code

#include <iostream>
#include <cstdio>
using namespace std;
int n,m;
long long f[12][(1<<12)];
void dfs(int h,int l,int now,int pre)
{
if(l>m+1)
return ;
if(l==m+1)
{
f[h][now]+=f[h-1][pre];
return ;
}
dfs(h,l+1,now<<1,(pre<<1)|1);//1情况
dfs(h,l+2,(now<<2)|3,(pre<<2)|3);//2情况
dfs(h,l+1,(now<<1)|1,pre<<1);//③情况
}
int main()
{
scanf("%d %d",&n,&m);
f[0][(1<<m)-1]=1;
for(int i=1;i<=n;i++)
dfs(i,1,0,0);
printf("%lld\n",f
[(1<<m)-1]);
return 0;
}


选课

Description

略(就是平常的选课题面,只不过要求输出最优方案)

Date Size

课程数<=500

Solution

看到这道题目的时候超惊喜的有没有,哇,竟然良心地考原题水题,超感动的有没有。愉快地打了树形DP,满心欢喜地以为AC了,开始测样例,然后突然发现要输出最优方案。于是乎,就挂了。

kb用的是DP两次,第一次跑答案,第二次利用答案跑方案,当然第二次的重复计算可以使用第一次跑出来的数据。不过按kb的说法是,更优的方案应该是,多叉树转二叉树,这样更好记录答案,然后排序输出就好了。

卡车更新问题

Description

某人购置了一辆新卡车, 从事个体运输业务. 给定以下各有关数据:

R[t], t=0,1,2,…,k, 表示已使用过 t 年的卡车, 再工作一年所得的运费, 它随 t 的增加而减少, k (k 年后卡车已无使用价值)。

U[t]: t=0,1,…,k, 表示已使用过 t 年的卡车, 再工作一年所需的维修费, 它随 t 的增加而增加.

C[t], t=0,1,2,…,k, 表示已使用过 t 年的旧卡车, 卖掉旧车, 买进新车, 所需的净费用, 它随 t 的增加而增加. 以上各数据均为实型, 单位为”万元”.

设某卡车已使用过 t 年,

① 如果继续使用, 则第 t+1 年回收额为 R[t]-U[t],

② 如果卖掉旧车,买进新车, 则 第 t+1年回收额为 R[0]-U[0]-C[t] .

该运输户从某年初购车日起,计划工作 N (N<=20) 年, N 年后不论车的状态如何,不再工作. 为使这 N 年的总回收额最大, 应在哪些年更新旧车? 假定在这 N 年内, 运输户每年只用一辆车, 而且以上各种费用均不改变.

Date Size

k<=20

Solution

好像是一道比较裸又比较水的DP,也没有什么好解释的,就直接上代码好了。

Code

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-10;
int n,k;
double ans=0,r[22],u[22],c[22],f[22][22];
void print(int x,int y){
double kl;
int i,j;
if(x==1)
{
printf("%d 0 %.1lf\n",x,f[x][0]);
return;
}
if(y==0)
for(i=0;i<x-1&&i<k;i++)
if(fabs(f[x-1][i]+r[0]-u[0]-c[i+1]-f[x][y])<eps)
{
print(x-1,i);printf("%d 1 %.1lf\n",x,f[x][y]-f[x-1][i]);
return;
}
print(x-1,y-1);
printf("%d 0 %.1lf\n",x,f[x][y]-f[x-1][y-1]);
}
int main()
{
freopen("truck.in","r",stdin);
freopen("truck.out","w",stdout);
int flag;
scanf("%d%d",&n,&k);
for(int i=0;i<=k;i++)
scanf("%lf",&r[i]);
for(int i=0;i<=k;i++)
scanf("%lf",&u[i]);
for(int i=0;i<=k;i++)
scanf("%lf",&c[i]);
f[1][0]=r[0]-u[0];
for(int i=2;i<=n;i++)
{
f[i][0]=f[i-1][0]+r[0]-u[0]-c[1];
for(int j=1;j<i-1&&j<k;j++)
f[i][0]=max(f[i][0],f[i-1][j]+r[0]-u[0]-c[j+1]);
for(int j=1;j<i&&j<=k;j++)
f[i][j]=f[i-1][j-1]+r[j]-u[j];
}
for(int i=0;i<n&&i<=k;i++)
if(f
[i]>ans)
ans=f
[i],flag=i;
printf("%.1lf\n",ans);
print(n,flag);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: