您的位置:首页 > 编程语言

9度-九度OJ之我与名企有个约会趣味编程系列赛(1)

2011-11-21 20:44 405 查看
A.液晶屏裁剪

简单题。题目给出的长宽比例可能不是最简形式,所以首先化简,然后放大这个最小比例直到最大的比当前的长宽小于或等于。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐