2017省夏令营Day6 【dp】

题解:区间dp,f[i][j]表示区间[i,j]的狼全部消灭的最小代价,设k为i、j间任意一点(i<=k<=j),且第k只狼被最后消灭,显然,区间总代价即可被我们划分成[i,k-1]和[k+1,j]两部分,我们可以假设他们已知,于是求得两区间代价和再加上消灭第k只狼的代价就能求得区间[i,j]的总代价.

状态转移方程:f[i][j]=f[i][k-1]+f[k+1][i]+a[k]+b[i-1]+b[j+1]。

PS:注意初始化时i要从0开始枚举,且若j<i时f值为0。

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define INF 0x7fffffff
 5 using namespace std;
 6 int n,a[405],b[405],f[405][405],g[405][405];
 7 int main()
 8 {
 9     freopen("wolf.in","r",stdin);
10     freopen("wolf.out","w",stdout);
11     scanf("%d",&n);
12     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
13     for(int i=1;i<=n;i++) scanf("%d",&b[i]);
14     for(int i=0;i<=n;i++)
15         for(int j=i;j<=n;j++){
16             if(i==j) f[i][j]=a[i]+b[j-1]+b[j+1];
17             else f[i][j]=INF;
18         }
19     for(int l=1;l<n;l++)
20         for(int i=1;i+l<=n;i++){
21             int j=i+l;
22             for(int k=i;k<=j;k++)
23                 f[i][j]=min(f[i][j],f[i][k-1]+f[k+1][j]+a[k]+b[i-1]+b[j+1]);
24         }
25     printf("%d",f[1][n]);
26     return 0;
27 }

-------------------------------------------------华丽的分割线---------------------------------------------------------------

题解:首先,我们预处理1-88的斐波那契数列 f,可以推出一条规律:如果只有第i个数为答案,答案数为(i+1)/2,如果不保留这个数(此位为0),答案为(i-1)/2(“例子见下“*”)

我们从大到小枚举斐波那契数,如果f[i]比n小那么就把i存入a数组并把n-f[i],a[i]表示第i个1所在斐波那契数列第几项,于是得出一个像二进制的01串,我们就可以从低位向高位dp。

状态转移方程:①g[i][1]=g[i-1][0]+g[i-1][1](如果第i个1还为1,那么加入这个点对答案无影响,直接转移即可)

②g[i][0]=g[i-1][1]*(a[i]-a[i-1]-1)/2+g[i-1][0]*(a[i]-a[i-1])/2 (如果第i个1变成0,表明第i个1变成了前2项的和并继续向前拓展,统计答案方法如上,但是要注意如果前一个1还为1统计答案时区间长度-1,因为前一个1的位置不能用于统计)

初始化:g[1][1]=1,g[1][0]=(a[1]-1)/2;

*:若斐波那契数列第5项为1,可以把第5项改为0,并把3、4两项改为1,第4项无法再修改,可把第3项改为0,并把1、2项修改为1,总答案数为(5+1)/2=3;若不包含第5项(为0),答案数为(5-1)/2=2;

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 long long n,f[90],a[90],g[90][2];
 7 int main()
 8 {
 9     freopen("fibonacci.in","r",stdin);
10     freopen("fibonacci.out","w",stdout);
11     f[1]=1; f[2]=2;
12     for(int i=3;i<=88;i++) f[i]=f[i-1]+f[i-2];
13     int T; scanf("%d",&T);
14     while(T--){
15         scanf("%lld",&n);
16         int cnt=0;
17         for(int i=88;i>=1;i--)
18             if(f[i]<=n){n-=f[i],a[++cnt]=1LL*i;}
19         reverse(a+1,a+cnt+1);
20         g[1][1]=1;
21         g[1][0]=(a[1]-1)>>1;
22         for(int i=2;i<=cnt;i++){
23             g[i][1]=g[i-1][0]+g[i-1][1];
24             g[i][0]=((a[i]-a[i-1]-1)>>1)*g[i-1][1]+((a[i]-a[i-1])>>1)*g[i-1][0];
25         }
26         printf("%lld\n",g[cnt][0]+g[cnt][1]);
27     }
28     return 0;
29 }
时间: 2024-10-04 01:48:59

2017省夏令营Day6 【dp】的相关文章

USACO 2017 FEB Platinum nocross DP

题目大意 上下有两个长度为n.位置对应的序列A.B,其中数的范围均为1~n.若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边.现要求在边与边不相交的情况下的最大的连边数量.n <= 10^5. 在Gold里,此题的数据范围是1000,我们完全可以用简单的最长公共连续子序列的DP方法来做. 范围大了之后,可以观察到对于一个数A[i],它所能转移的状态最多只有9个,那么就可以顺序扫描A数组,设F[i][j]表示当前连得最后一条边为(A[i],B[to[i][j]])的最

2017山东夏令营测验 D5T1 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 小菜一碟的背包题目描述有n头奶牛,每头奶牛有食量w[i]和产奶量v[i],每天能够提供W千克草料.选取奶牛使产奶总量尽可能大,问最大是多少.输入格式第一行两个整数 ,表示奶牛的数量和每天最多能提供的草接下来i行,每行两个整数,第i行表示第I头奶牛的产奶量和食量输出格式仅一行,输出一个整数,表示每天最大的总产奶量输入样例8 4010 912 1111 1210 108 117 98 109 10输出样例41限制与约定对于所有数据

2017省夏令营Day7 【快速幂,筛法,矩阵快速幂,线段树】

题解:首先,我们可以得到一个规律:经过2次变换后,a和b的值都分别乘2了,所以只要用快速幂就能过啦,但是,要特判n为0的情况. 代码如下: 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define Mod 1000000007 5 using namespace std; 6 long long a,b,n,ans1,ans2; 7 long long power(long long x)

2017省夏令营Day8 【bfs,并查集】

题解:出题人丧心病狂~ 对于这道题,我们对每一个内应节点bfs,并用并查集维护,如果s和t联通,输出答案并break. PS几个小细节:①对于每个内应dis=0,为了保证不会对答案产生影响,我们在每2个节点中插入一个新的节点即可: ②因为加入新节点,数组要开大些,否则会炸. 代码如下: 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define Max 2020304 5 using nam

NKOJ 2017信息学夏令营第1场(图论专项练习)

A题: 网络流最大流模型. 用 [1, m] 表示各个国家,[m+1, m+n] 表示各个餐桌. 从 s 向 i 连边,容量为第 i 个国家的代表数: 从 m+i 向 t 连边,容量为第 i 张餐桌的容量: 从 i 向 j + m 连边,容量为 1 ,这样就限制了每个国家在一个餐桌上至多有一个代表. 找到最大流,表示满足条件的代表数量最大值,再与提前计算出的代表总数量比较, 两者如果相等说明存在合理方案,输出 1 ,否则输出 0. B题: 二分图的最大匹配模型. 我在比赛的时候考虑了费用流,在"

2017福建夏令营Day1(数据结构)

工作团队 [问题描述] 一家公司有??名员工,刚开始每个人单独构成一个工作团队. 有时一项工作仅凭一个人或一个团队难以完成,所以公司会让某两个 人所在的团队合并. 但有的工作属于闷声大发财类型的,不适合多人做,所以公司有时也 会让一个人从他当前所在的团队中分离出来,构成单独的团队. 公司也要对当前团队的情况进行了解,所以他们也会询问一些问题, 比如某两个人是否属于同一工作团队,某个人所在的团队有多少个人,或 者当前一共有多少个工作团队. 作为该公司的软件服务商,你的任务便是实现一个实时的操作和查

Hackrank Equal DP

Christy is interning at HackerRank. One day she has to distribute some chocolates to her colleagues. She is biased towards her friends and may have distributed the chocolates unequally. One of the program managers gets to know this and orders Christy

P1193扫雷 (DP状态压缩)

P1193扫雷 Accepted 标签:[显示标签] 描述 相信大家都玩过扫雷的游戏.那是在一个n*n的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,"余"任过流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和他8连通的格子里面雷的数目.现在棋盘是n*2的,第一列里某些格子是雷,而第二列没有雷,如: o 1 * 2 * 3 * 2 o 2 * 2 * 2 ('*'代表有雷,'o'代表无雷) 由于第一类的雷有可能有多种方案满足第二列的

同花顺

洛谷P2652 同花顺 这是在2017日照夏令营的D1T2,我认为质量相当高的一道题,第一次在赛场上做的时候爆零了,当时态度不很端正,暴力不想打,想投机取巧骗分,还是不要把希望压在不确定的事情上,有多少分实实在在拿着就拿着,然后能力之外的再尽可能获得更多.言归正传,这个用类似枚举的思路来做,枚举一个同花顺的左右端点,具体是外循环先确定j,然后枚举可能的第一个左端点,然后用n-max(ans):这个的证明是向李子晗学习的,回来后我又在洛谷上做了一遍,50分.接下来是核心部分:先说我为什么是错的,我