您的位置:首页 > 大数据 > 人工智能

2012 Multi-University Training Contest 2

2012-07-28 17:14 435 查看
1001 排序+贪心(不会状态DP)

题意:假设你的血是无限的但是攻击力只有1,给出N个人的dps和hp,你每攻击一个人,那么这个人的血量减一,同时你的血量减少值为所有活着的人的dps和,求最小花费多少血量可以把人全干倒。

思路:按照dps/hp 排序 ,优先把dps/hp数值高的人干掉。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct person {
int dps;
int hp;
};
person p[35];
int cmp(person a , person b) {
if((1.0*a.dps/a.hp) >= (1.0*b.dps/b.hp)) return 1;
else if((1.0*a.dps/a.hp) == (1.0*b.dps/b.hp)) {
if(a.hp <= b.hp) return 1;
return 0;
}
return 0;
}
int main() {
int N , i;
while(cin>>N) {
for(i = 0 ; i < N ; i ++) {
cin>>p[i].dps>>p[i].hp;
}
sort(p , p + N , cmp);
long long j , ans = 0;
long long ss = 0;
for(i = 0 ; i < N ; i ++) {
ans += p[i].dps*p[i].hp;
ss = 0;
for(j = i+1 ; j < N ; j ++) {
ss += p[j].dps;
}
ss *= p[i].hp;
ans += ss;
}
cout<<ans<<endl;
}
}


1002 巧妙的枚举

题意:给出一些点,找出一个点,使得其它点到这个点的曼哈顿距离最小。

平面上两点间的 Manhattan 距离为 |x1-x2| + |y1-y2|

思路:直接枚举肯定TLE , 但是可以x方向和y方向分别计算。先把点按照x升序排序,要求出其它点到xi的距离∑|x -
xi| ,pre[i] 代表小于等于xi的x的和,sumx[i]代表其它点到点i的x方向的曼哈顿距离。然后所有的sumx[i]都可以通过pre[i]推出,sumx[p[i].pos] = pre
- 2*pre[i] + (2*i-n)*p[i].x;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 100100;
struct point {
ll x;
ll y;
int pos;   //因为排序后 点的原始位置被打乱 所以用pos记录原始点的位置
}p[maxn];
ll pre[maxn]; // 以xi为最大的数 小于等于xi的累加和
ll sumx[maxn] , sumy[maxn]; //x 、y 方向上的和
int cmp1(point a , point b) {
return a.x < b.x;
}
int cmp2(point a , point b) {
return a.y < b.y;
}
int main() {
int T , n;
cin>>T;
while(T--) {
cin>>n;
int i;
for(i = 1 ; i <= n ; i ++) {
cin>>p[i].x>>p[i].y;
p[i].pos = i;
}
memset(sumx , 0 , sizeof(sumx));
memset(sumy , 0 , sizeof(sumy));
memset(pre , 0 , sizeof(pre));
sort(&p[1] , &p[n+1] , cmp1);//x升序排序
pre[1] = p[1].x;
for(i = 2 ; i <= n ; i ++)
pre[i] = pre[i-1] + p[i].x;
for(i = 1 ; i <= n ; i ++) {
sumx[p[i].pos] = pre
- 2*pre[i] + (2*i-n)*p[i].x;
//cout<<"sumx = "<<sumx[p[i].pos]<<" "<<p[i].pos<<" "<<p[i].x<<" "<<p[i].y<<endl;
}
//for(i = 1 ; i <= n ; i ++)
//cout<<sumx[i]<<" ";
memset(pre , 0 , sizeof(pre));
sort(&p[1] , &p[n+1] , cmp2);
pre[1] = p[1].y;
for(i = 2 ; i <= n ; i ++)
pre[i] = pre[i-1] + p[i].y;
for(i = 1 ; i <= n ; i ++) {
sumy[p[i].pos] = pre
- 2*pre[i] + (2*i-n)*p[i].y;
}
ll ans;
ans = sumx[1] + sumy[1];
for(i = 1 ; i <= n ; i ++) {
if(sumx[i] + sumy[i] < ans)
ans = sumx[i] + sumy[i];
}
cout<<ans<<endl;
}
}

1006 Nim阶梯博弈变型

详解:xiuyang详解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main() {
int i , N , k , a[1010];
while(~scanf("%d%d",&N,&k)) {
for(i = 0 ; i < N ; i ++)
scanf("%d",&a[i]);
if(k == 1) {
printf("Alice\n");
continue;
}
int ans = 0;
if(N%2==0) {
for(i = 0 ; i < N - 1 ; i += 2)
ans = ans^(a[i+1] - a[i] - 1);
}
if(N%2==1) {
if(k==2) a[0]--;
ans = a[0];
for(i = 1 ; i < N - 1 ; i += 2)
ans = ans^(a[i+1] - a[i] - 1);
}
if(!ans) printf("Bob\n");
else printf("Alice\n");
}
}


1009 spfa

题意:就是求图上s点到t点的最小power损失,松弛条件改改就行。

SPFA不熟,好多细节没有注意到,跪了好久。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf 0xfffffff
const int maxm = 2610000;
const int maxn = 51000;
struct edge {
int v;
double w;
int nex;
}e[maxm];
int head[maxn];
bool vis[maxn];
double d[maxn];
int k;
void add_edge(int a , int b , double w) {                 //加边
e[k].v = b;
e[k].w = w;
e[k].nex = head[a];
head[a] = k++;
}
void spfa(int s , int m) {
queue<int> Q;
d[s] = 0;
vis[s] = 1;
Q.push(s);
int t;
while(!Q.empty()) {
t = Q.front();
Q.pop();
vis[t] = 0;
int j;
for(j = head[t] ; j!=-1 ; j = e[j].nex) {
int v = e[j].v;
double w = e[j].w;
if(d[v] > d[t] + (double)(m-d[t])*w) {
d[v] = d[t] + (double)(m-d[t])*w;
if(!vis[v]) {
Q.push(v);
vis[v] = 1;
}
}
}
}
}
int main() {
int n;
while(scanf("%d",&n)!=EOF) {
int c , b;
double w;
memset(head , -1 , sizeof(head));
k  = 1;
for(int i = 1 ; i <= n ; i ++) {
cin>>c;
while(c--) {
cin>>b>>w;
w = (double)w/100.0;
add_edge(i , b , w);
}
}
int s , t , m;
scanf("%d%d%d",&s,&t,&m);
for(int i = 0 ; i <= n ; i ++) d[i] = inf;
memset(vis , 0 , sizeof(vis));
spfa(s , m);
if(d[t]!=inf)
printf("%.2lf\n",d[t]);
else
printf("IMPOSSIBLE\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: