DP 入门提练习解题报告
来源:互联网 发布:数据库从入门到精通 编辑:程序博客网 时间:2024/05/17 06:38
所有的代码都在这里 ,新队员们做不出来的题可以先参考我的代码,能自己讨论出来的尽量先多讨论(结合我的代码)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=29041#overview
我会一个个题更新。。。。
以前写过几个简单的dp入门提
http://blog.csdn.net/haha593572013/article/details/7834532
B - Marriage Ceremonies
学习资料
http://wenku.baidu.com/view/8c9bd904de80d4d8d15a4fd4.html
这道题纯暴力的复杂度是16!,肯定是没法过的。。。
可以想到这样的状态,当我们在决策第i行应该选哪一列的时候,我们需要知道前面i-1行已经选了哪些列了,对于这些列,我们并不关心到底是哪些行选择了这些列 ,我们关心的只是一个最大的权值和,即前i-1行已经选择了某个集合的列的前提下所能获取的最大权值和,然后我们枚举这个集合中还没有被选择的列在第i行进行状态转移。
那么接下来的事情就是怎么表示这个集合了。我们可以将这个集合压缩成一个整数,用这个整数的二进制表示来描述这个集合,然后我们可以发现我们可以用2^16个数来描述所有的状态了。
101011 = 43
上面这个状态代表的意义是第0 , 1 ,3 , 5 列都已经选择了。
我们就用 43这个数字来描述这个状态。
一些二进制的基本知识
判断j是否属于集合i:i&(1<<j)是否大于0(即是否等于2^j)
在集合i中去除j:i-(1<<j)或者i&(!(1<<j)) , i^(1<<j)
在集合i中加入点j:i|(1<<j);
#include<cstdio>#include<cstring>const int maxn = 100010;const int mod = 1000000007;int dp[17][1<<17];int a[17][17];int main(){int n;int t,ca=1;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){scanf("%d",&a[i][j]);}}for(int i = 0; i < n; i++){for(int j = 0; j < two[n]; j++) dp[i][j] = -1;//一开始所有的状态都是非法的}for(int i = 0; i < n; i++) dp[0][1<<i] = a[0][i];for(int i = 1; i < n; i++){ //枚举前i-1行所有已经存在的状态,去更新前i行的状态for(int j = 0; j < (1<<n); j++) if(dp[i-1][j]!=-1)//前i-1行j的状态存在的前提下才能转移{ for(int k = 0; k < n; k++) if(!(j&(1<<k))) // k 不在j集合中 { dp[i] [j | ( 1<<k ) ] = max(dp[i][j | ( 1<<k ) ],dp[i-1][j] + a[i][k]); }}}printf("Case %d: ",ca++);printf("%d\n",dp[n-1][(1<<n)-1]);}return 0;}
C - Love Calculator、
这个题本质其实就是LCS(longest comman sequence)的变形,想想看,最终构成的字符串的长度肯定是两个串的长度相加减去lcs的长度,但是有多少的这样的串呢?
初做dp的话还真是挺难想的,不过DP靠的就是多做多练了,感觉嘛,培养培养就有了,考虑这样的状态dp[i][j][k],表示构造了i长度的字符串,利用了第一个串的前i个字符以及第二个字符串的前j个字符,这个状态的意义就是当前状态下总的方案数,那么现在考虑转移,其实我们是要在后面继续扩充一个字符,如果a[j+1] = b[k+1],就可以转移到dp[i+1][j+1][k+1]的状态,
否则,可以转移到dp[i+1][j][k+1]或者dp[i+1][j+1][k];
求完DP后,我们需要寻找我们的答案,这个大家可以好好想想,应该不难。
同样的,还是贴上AC代码
注:代码一定要独立完成,切不可肆意模仿甚至抄袭。。。。
#include<set>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 100010;const int mod = 1000000007;long long dp[65][35][35];char s1[110],s2[110];int main(){int t,ca=1;scanf("%d",&t);while(t--){scanf("%s%s",s1+1,s2+1);int n = strlen(s1+1);int m = strlen(s2+1);s1[n+1] = '@'; s2[m+1]='@';for(int i = 0; i <= m+n; i++){for(int j = 0; j <= n; j++){for(int k = 0; k <= m; k++){dp[i][j][k] = 0;}}}dp[0][0][0] = 1;for(int i = 0; i <= m+n; i++){for(int j = 0; j <= n; j++){for(int k = 0; k <= m; k++) if(dp[i][j][k]){if(s1[j+1]==s2[k+1]){dp[i+1][j+1][k+1] += dp[i][j][k];}if(s1[j+1]!=s2[k+1]) {dp[i+1][j+1][k] += dp[i][j][k];dp[i+1][j][k+1] += dp[i][j][k];}}}}int ans_len = -1;for(int i = 1; i <= m+n; i++){if(dp[i][n][m]){ans_len = i;break;}}printf("Case %d: %d %lld\n",ca++,ans_len,dp[ans_len][n][m]);}return 0;}
- DP 入门提练习解题报告
- 最短路入门练习 解题报告
- 动态规划(dp)入门解题报告
- HDU 2602 Bone Collector 解题报告(dp入门题)
- 【DP】2479解题报告
- HDU1864解题报告-dp
- 20111023练习赛解题报告
- HLJU@贪心练习 解题报告
- CCNU 2010新生练习赛(DP)[差很多的解题报告]
- HDU4089概率dp解题报告
- hdu 1024 dp 解题报告
- 解题报告:HDU_3944 DP? 数论
- 解题报告: POJ_2955 Brackets DP
- Poj 1260 DP 解题报告
- POJ 1260 DP解题报告
- POJ 1160 DP 解题报告
- BZOJ 1820 DP 解题报告
- BZOJ 1566 DP 解题报告
- Necklace of Beads(hdu1817,ploay定理)
- XCode常用快捷键
- 基于用户的deviantArt推荐系统(SVD因子分解)
- android新的UI调试工具
- JPA的CRUD操作,映射实体
- DP 入门提练习解题报告
- Android入门:File文件存储
- 图片缓存管理
- HDU 1250Hat's Fibonacci(两种方法处理大数)
- JPA的关系映射和JPQL查询
- 微信公共平台开发接收与发送信息类型
- EJB
- insmod不匹配问题的解决
- ckeditor用户自定义配置文件config.js