9度-九度OJ之我与名企有个约会趣味编程系列赛(1)
2011-11-21 20:44
405 查看
A.液晶屏裁剪
简单题。题目给出的长宽比例可能不是最简形式,所以首先化简,然后放大这个最小比例直到最大的比当前的长宽小于或等于。
B.寻找最长合法括号序列
栈的应用,模拟题。首先得分析出,最长合法括号序列肯定是独立存在的,不存在两个最长合法括号序列重叠的情况,若重叠只能得到一个更长的序列。那么,我们需要一个辅助数组记录原序列当中哪些括号是被匹配过的,记1。然后再线扫这个辅助数组中最长连续的1的个数。
C.角斗士
状态压缩DP。初看规模,n只有18,马上想到是dfs搜索或者是状态压缩dp。介于dp本人不是很强,比赛中没想出去,赛后看了一些别人的思路。
令数组dp[x]表示x在二进制上为1那些人活着的概率,比如现在只有3个人,那么dp[5]表示第一个人和第三个人活着的概率。由于比赛是随即选择两个人,那么每场比赛的概率为1 / C(活着的人的个数,2)。最终的概率应该是叠加上去。
那么状态转移方程为dp[i ^ (1 << j)] += dp[i] * win[j][k] / pos。
简单题。题目给出的长宽比例可能不是最简形式,所以首先化简,然后放大这个最小比例直到最大的比当前的长宽小于或等于。
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <queue> using namespace std; int gcd(int x,int y) { int n; while(y) { n=x%y; x=y; y=n; } return x; } int main() { int a, b, c, d; while(scanf("%d %d %d %d", &a, &b, &c, &d) != EOF){ int x, y; x = gcd(c, d); c = c / x; d = d / x; x = a / c; y = b / d; x = x>y?y:x; printf("%d %d\n", c * x, d * x); } return 0; }
B.寻找最长合法括号序列
栈的应用,模拟题。首先得分析出,最长合法括号序列肯定是独立存在的,不存在两个最长合法括号序列重叠的情况,若重叠只能得到一个更长的序列。那么,我们需要一个辅助数组记录原序列当中哪些括号是被匹配过的,记1。然后再线扫这个辅助数组中最长连续的1的个数。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<iomanip> #include<string> #include<algorithm> #include<ctime> #include<stack> #include<queue> #include<vector> #define N 1000005 using namespace std; char str ,sub ; stack<int> s; int match(int a,int b) { if(str[a]=='('&&str[b]==')') return 1; return 0; } int main() { int len,i,j,l,start,end; while(cin>>len>>str) { memset(sub,0,sizeof(sub)); s.push(0); for(i=1;i<len;i++) { if(s.empty()) s.push(i); else if(match(s.top(),i)){ sub[s.top()]=1; sub[i]=1; s.pop(); } else s.push(i); } i=start=end=l=0; int num = 0; while(i<len){ j=0; while(i<len&&sub[i]==0) i++;j=i; while(i<len&&sub[i]) i++; if(i-j>l){ l=i-j; start=j; end=i; num=1; } else if(i-j==l){ num++; } } printf("%d %d\n",end-start, num); } return 0; }
C.角斗士
状态压缩DP。初看规模,n只有18,马上想到是dfs搜索或者是状态压缩dp。介于dp本人不是很强,比赛中没想出去,赛后看了一些别人的思路。
令数组dp[x]表示x在二进制上为1那些人活着的概率,比如现在只有3个人,那么dp[5]表示第一个人和第三个人活着的概率。由于比赛是随即选择两个人,那么每场比赛的概率为1 / C(活着的人的个数,2)。最终的概率应该是叠加上去。
那么状态转移方程为dp[i ^ (1 << j)] += dp[i] * win[j][k] / pos。
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <queue> using namespace std; double pos[1 << 18]; double win[18][18]; int Cout1Num(int n) { int x = 0; while(n){ x++; n = n & (n - 1); } return x; } int main() { int n; while (scanf("%d", &n) != EOF) { int i, j, k; for (i = 0; i < n; ++i) { for (j = 0; j < n; ++j) { scanf("%lf", &win[i][j]); } } memset(pos, 0, sizeof(pos)); pos[(1 << n) - 1] = 1.0; for (k = (1 << n) - 1; k > 0; --k) { int c = Cout1Num(k); int sum = c * (c - 1) / 2; if (c == 1) { continue; } for (i = 0; i < n; ++i) { if ((k & (1 << i)) == 0) { continue; } for (j = i + 1; j < n; ++j) { if ((k & (1 << j)) == 0) { continue; } pos[k ^ (1 << j)] += pos[k] * win[i][j] / sum; pos[k ^ (1 << i)] += pos[k] * win[j][i] / sum; } } } for (i = 0; i < n; ++i) { if(i) printf(" "); printf("%lf", pos[1 << i]); } printf("\n"); } return 0; }
相关文章推荐
- 9度-九度OJ之我与名企有个约会趣味编程系列赛(2)
- 【剑指Offer面试编程题】题目1508:把字符串转换成整数--九度OJ
- 【剑指Offer面试编程题】题目1511:从尾到头打印链表--九度OJ
- 【剑指Offer面试编程题】题目1522:包含min函数的栈--九度OJ
- 【剑指Offer面试编程题】题目1354:和为S的连续正数序列--九度OJ
- 【剑指Offer面试编程题】题目1508:把字符串转换成整数--九度OJ
- 【剑指Offer面试编程题】题目1511:从尾到头打印链表--九度OJ
- 【剑指Offer面试编程题】题目1388:跳台阶--九度OJ
- 【剑指Offer面试编程题】题目1522:包含min函数的栈--九度OJ
- 【剑指Offer面试编程题】题目1354:和为S的连续正数序列--九度OJ
- 【剑指Offer面试编程题】题目1388:跳台阶--九度OJ
- 【剑指Offer面试编程题】题目1516:调整数组顺序使奇数位于偶数前面--九度OJ
- 【九度OJ】1017【BST】【畅通工程系列2006】
- 【剑指Offer面试编程题】题目1516:调整数组顺序使奇数位于偶数前面--九度OJ
- 【剑指Offer面试编程题】题目1283:第一个只出现一次的字符--九度OJ
- 【九度OJ】1015【模拟】【A+B系列2006】
- 【剑指Offer面试编程题】题目1283:第一个只出现一次的字符--九度OJ
- 【剑指Offer面试编程题】题目1524:复杂链表的复制--九度OJ
- 【剑指Offer面试编程题】题目1372:最大子向量和--九度OJ
- 【剑指Offer面试编程题】题目1366:栈的压入、弹出序列--九度OJ