|
摘要: 题目大意:16个人举行宴席,4人一桌,一共5次。(严重不符合客观事实。。)求怎样安排才能使每次吃饭时,每个人的同桌都是不同的人。也就是说吃完5次饭下来,每个人都认识其他人了。。有人帮你算好了前3次的情况,你需要接着算出余下的2次,当然也有可能算不出来。思路:暴搜,位操作辅助。ps:此题描述得不大清楚,导致屡次wa。注意:1.多case2.如果有解,需要打印5行。3.如果无解,只需要打印“... 阅读全文
摘要: 这题很有意思哇。给出一个这样的东西:A---+ | +---:\ : >o---:\ +---:/ : )---?&... 阅读全文
这题好题啊,网上也有很多解题报告的呢,哥也是看了才懂写的。。 直接贴代码。这个代码不咋地呢。 分数规划用迭代法500+ms,用二分法就2000+ms了。可见差异还是挺大的,还是迭代法好。 膜拜下分数规划算法的创始人
#include <stdio.h>
#include <math.h>
#include <string.h>

int X[1024], Y[1024], Z[1024], N, from[1024];
char mst[1024];
double D[1024], rate;
 struct {
double w, cost, len;
} E[1024][1024];

double prim(double L)
  {
int i, j;
double res, cost, len;

for (i = 0; i < N; i++)
for (j = i; j < N; j++)
E[i][j].w = E[j][i].w = E[i][j].cost - E[i][j].len * L;

 for (i = 0; i < N; i++) {
D[i] = E[0][i].w;
from[i] = 0;
}
memset(mst, 0, N);
mst[0] = 1;

res = cost = len = 0;
 for (i = 0; i < N - 1; i++) {
double min_d;
int min_i;

min_d = 1e50;
 for (j = 0; j < N; j++) {
 if (!mst[j] && D[j] < min_d) {
min_d = D[j];
min_i = j;
}
}

mst[min_i] = 1;
res += min_d;
cost += E[min_i][from[min_i]].cost;
len += E[min_i][from[min_i]].len;

 for (j = 0; j < N; j++) {
 if (!mst[j] && E[min_i][j].w < D[j]) {
D[j] = E[min_i][j].w;
from[j] = min_i;
}
}
}

rate = cost / len;
return res;
}


void solve()
  {
 /**//*
double l, r, m;

l = 0;
r = 1000;
while (r - l > 0.0001) {
m = (r + l) / 2;
if (prim(m) > 0)
l = m;
else
r = m;
}
*/
double r;
int i, j;

 for (i = 0; i < N; i++) {
 for (j = i; j < N; j++) {
double dx, dy;
dx = (double)X[i] - X[j];
dy = (double)Y[i] - Y[j];
E[i][j].cost = E[j][i].cost = fabs((double)Z[i] - Z[j]);
E[i][j].len = E[j][i].len = sqrt(dx*dx + dy*dy);
}
}

rate = 0;
 do {
r = rate;
prim(rate);
} while (fabs(r - rate) > 0.0001);

printf("%.3f\n", rate);
}

int main()
  {
int i;

freopen("e:\\test\\in.txt", "r", stdin);

 while (1) {
scanf("%d", &N);
if (!N)
break;
for (i = 0; i < N; i++)
scanf("%d%d%d", &X[i], &Y[i], &Z[i]);
solve();
}
return 0;
}

题目大意: A,B两个sb比赛吃葡萄,葡萄上有编号1,2,....100,得分是每个人吃过葡萄的编号的乘积。 比如吃了 2, 5, 10 号葡萄,分数就是 2*5*10 = 100。 葡萄吃完后,两个人报自己的分数。当然,可以虚报。 如果某个人报的分数是吃不出来的,那就算他作弊,另外一个人赢。 如果两个人报的分数有冲突,则分数低的赢。 如果两个人报的分数没有冲突,则分数高的赢。
思路: 枚举每个人吃葡萄的所有情况。。
#include <stdio.h>
#include <string.h>

__int64 val2;
char used[101];

int dfs(__int64 val, int idx, int flag)
  {
 if (val == 1 || val == 0) {
if (!flag)
return 1;
return dfs(val2, 100, 0);
}

 for ( ; idx > 1; idx--) {
if (!(val % idx) && !used[idx])
break;
}
if (idx == 1)
return 0;

used[idx] = 1;
if (dfs(val / idx, idx - 1, flag))
return 1;
used[idx] = 0;

if (dfs(val, idx - 1, flag))
return 1;

return 0;
}

int can(__int64 val, int flag)
  {
memset(used, 0, sizeof(used));
return dfs(val, 100, flag);
}

int main()
  {
__int64 a, b, r;

 while (scanf("%I64d%I64d", &a, &b) != EOF) {
 if (a > b) {
r = a;
a = b;
b = r;
}
val2 = b;
if (!can(a, 0))
r = b;
else if (!can(b, 0))
r = a;
else if (can(a, 1))
r = b;
else
r = a;
printf("%I64d\n", r);
}
return 0;
}

题目大意: 给出一个分数,比如1498/902。求出当分母分别为1, 2, ....的时候,最接近1498/902的分数。 比如: 当分母为1的时候,最接近1498/902的分数为 1/1。 当分母为2的时候,最接近1498/902的分数为 3/2。 当分母为3的时候,最接近1498/902的分数为 5/3。 。。。
思路: 不要用高精度哦,直接模拟分数的操作最好了。
#include <stdio.h>
#include <math.h>

 struct frac {
__int64 up, down;
};

__inline __int64 gcd(__int64 a, __int64 b)
  {
__int64 r;

 if (a < b) {
r = a;
a = b;
b = r;
}

 while (1) {
r = a % b;
if (!r)
return b;
a = b;
b = r;
}
}

__inline struct frac frac_init(__int64 up, __int64 down)
  {
__int64 r, s;
struct frac f;

r = up ? gcd(up, down) : 1;
if (r < 0)
r = -r;
f.up = up / r;
f.down = down / r;
return f;
}

__inline struct frac frac_sub(struct frac fa, struct frac fb)
  {
return frac_init(fa.up*fb.down-fa.down*fb.up, fa.down*fb.down);
}

__inline __int64 frac_cmp(struct frac fa, struct frac fb)
  {
return frac_sub(fa, fb).up;
}

__inline struct frac frac_abs(struct frac f)
  {
if (f.up < 0)
f.up = -f.up;
return f;
}

int main()
  {
__int64 up, down;
struct frac target, min_dis, f, dis;

 while (scanf("%I64d%I64d", &up, &down) != EOF) {
target = frac_init(up, down);
min_dis.down = 1;
min_dis.up = (__int64)1e15;
 for (down = 1; down <= target.down; down++) {
up = (down*target.up)/target.down;
if (((down*target.up)%target.down)*2 >= target.down)
up++;
f = frac_init(up, down);
dis = frac_abs(frac_sub(f, target));
 if (frac_cmp(dis, min_dis) < 0) {
printf("%I64d/%I64d\n", f.up, f.down);
min_dis = dis;
}
}
printf("\n");
}

return 0;
}

题目大意: 有一群学生,其中有些人是相互认识的。将学生分为两组,这两组的人数最大只能相差1。 定义一个学生的“孤独指数”为组内他不认识的人的人数。 问怎么分组,才能使这两组中最孤独学生的“孤独指数”最小。
思路: 想不到算法,于是看Discuss。原来是用枚举。。 暴力枚举每一种分组情况,求该情况下“最孤独学生的孤独指数”。 据说数据很弱,N最大才是4,囧。所以0msAC。
#include <stdio.h>

unsigned __int64 map[64];
int N;
int bit_cnt[256];

__inline int calc_cnt(unsigned __int64 val)
  {
return bit_cnt[((char *)&val)[0]] +
bit_cnt[((char *)&val)[1]] +
bit_cnt[((char *)&val)[2]] +
bit_cnt[((char *)&val)[3]] +
bit_cnt[((char *)&val)[4]] +
bit_cnt[((char *)&val)[5]] +
bit_cnt[((char *)&val)[6]] +
bit_cnt[((char *)&val)[7]];
}

__inline int min(int a, int b)
  {
return a < b ? a : b;
}

__inline int max(int a, int b)
  {
return a < b ? b : a;
}

int main()
  {
int i, j, k, l, r, arr[64], min_val;
unsigned __int64 mask;

freopen("e:\\test\\in.txt", "r", stdin);

 for (i = 0; i < 256; i++) {
k = 0;
for (j = i; j; j &= j - 1)
k++;
bit_cnt[i] = k;
}

 while (scanf("%d%d", &j, &k) != EOF) {
 while (k--) {
scanf("%d", &i);
map[j] |= (unsigned __int64)1 << i;
}
if (j > N)
N = j;
}
for (i = 1; i <= N; i++)
map[i] |= (unsigned __int64)1 << i;

min_val = N;
for (i = 1; i <= N/2; i++)
arr[i] = i;
 while (1) {
mask = 0;
for (i = 1; i <= N/2; i++)
mask |= (unsigned __int64)1 << arr[i];
l = r = N;
 for (i = 1; i <= N; i++) {
if (mask & ((unsigned __int64)1 << i))
l = min(calc_cnt(map[i] & mask), l);
else
r = min(calc_cnt(map[i] & ~mask), r);
}
i = max(N/2 - l, N - N/2 - r);
if (i < min_val)
min_val = i;
for (i = N/2; i >= 1 && arr[i] == N + i - N/2; i--);
if (!i)
break;
arr[i]++;
for (j = 1; j + i <= N/2; j++)
arr[j + i] = arr[i] + j;
}
printf("%d\n", min_val);
return 0;
}

|