您的位置:首页 > 其它

gdut校赛决赛题解

2016-04-21 12:38 274 查看
比较水的比赛,水下博客贴个题解。

Problem A: Krito的讨伐

直接模拟,把可见范围内的怪物都扔进优先队列,先杀防御低的,最后判断还有没有怪剩余就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef struct Mon
{
int def;
int add;
int r;
bool operator <(const Mon &r)const
{
return r.def<def;
}
} Mon;

typedef struct
{
int num;
vector<Mon>M;
} room;

priority_queue<Mon>que;
int t;
int n,m;
long long int atk;
bool dis[1005][1005];
room R[1005];
bool vis[1005];
bool flag=0;
void add(int num)
{
vis[num]=1;
if(R[num].num==0)
{
for(int i=0;i<n;i++)
{
if(dis[num][i] && vis[i]==0)
add(i);
}
}
else
{
for(int i=0;i<R[num].num;i++)
que.push(R[num].M[i]);
}
}
bool solve()
{
Mon tmp;
add(0);
while(!que.empty())
{
tmp=que.top();
if(atk<tmp.def)
{
break;
}
que.pop();
atk+=tmp.add;
R[tmp.r].num--;
if(R[tmp.r].num==0)
{
for(int i=0;i<n;i++)
{
if(dis[tmp.r][i] && vis[i]==0)
{
add(i);
}
}
}
}
long long int left=0;
for(int i=0; i<n; i++)
{
left+=R[i].num;
}
if(left>0)
return 0;
return 1;
}

int main()
{
cin >> t;
int a,b,c;
Mon tmp;
while(t--)
{
cin >> n >> m;
while(!que.empty())que.pop();
memset(dis,0,sizeof(dis));
memset(R,0,sizeof(R));
memset(vis,0,sizeof(vis));
for(int i=0; i<n-1; i++)
{
scanf("%d%d",&a,&b);
dis[a][b]=dis[b][a]=1;
}
cin >> atk;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
R[a].num++;
tmp.def=b,tmp.add=c;
tmp.r=a;
R[a].M.push_back(tmp);
}
if(solve())
cout << "Oh yes." << endl;
else
cout << "Good Good Study,Day Day Up." << endl;
}
return 0;
}


Problem B: Sward Art Online

我直接写了几个DP,貌似有菊苣枚举+DP,都是可以的。

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
long long int t,m,a,b,c,d;
long long int dp1[100005],dp2[100005],dp3[100005],dp4[100005];
long long int num[100005];
typedef struct
{
int atk,cost;
}node;
typedef struct
{
long long int atk,cost,num,buff;
}newnode;
node tou[100005];
newnode shou[100005];
node wuqi[100005];
node wuqi2[100005];
int main()
{
//freopen("input.txt","r",stdin);
cin >> t;
node temp;
newnode temp1;
long long int tmp,tmpa,tmpb,tmpc;
while(t--)
{
memset(num,-1,sizeof(num));
cin >> m >> a >> b >> c >> d;
for(long long int i=0;i<a;i++)
{
scanf("%lld%lld",&tmp,&tmpa);
temp.cost=tmp;
temp.atk=tmpa;
tou[i]=temp;
}
for(long long int i=0;i<b;i++)
{
scanf("%lld%lld%lld%lld",&tmp,&tmpa,&tmpb,&tmpc);
temp1.cost=tmp,temp1.atk=tmpa,temp1.num=tmpb,temp1.buff=tmpc;
shou[i]=temp1;
}
for(long long int i=0;i<c;i++)
{
scanf("%lld%lld",&tmp,&tmpa);
temp.cost=tmp;
temp.atk=tmpa;
wuqi[i]=temp;
}
for(long long int i=0;i<d;i++)
{
scanf("%lld%lld",&tmp,&tmpa);
temp.cost=tmp;
temp.atk=tmpa;
wuqi2[i]=temp;
}

for(long long int i=0;i<a;i++)
{
temp=tou[i];
if(m-temp.cost<0)
continue;
if(dp1[m-temp.cost]<temp.atk)
{
dp1[m-temp.cost]=temp.atk;
num[m-temp.cost]=i;
}
}
memcpy(dp2,dp1,sizeof(dp1));
for(long long int i=0;i<b;i++)
{
temp1=shou[i];
for(long long int j=temp1.cost;j<=m;j++)
{
if(temp1.num!=-1 && temp1.num==num[j])
{
if(dp2[j-temp1.cost]<dp1[j]+temp1.buff+temp1.atk)
{
dp2[j-temp1.cost]=dp1[j]+temp1.buff+temp1.atk;
}
}
else
{
if(dp2[j-temp1.cost]<dp1[j]+temp1.atk)
dp2[j-temp1.cost]=dp1[j]+temp1.atk;
}
}
}
memcpy(dp3,dp2,sizeof(dp2));
memset(num,-1,sizeof(num));
for(long long int i=0;i<c;i++)
{
temp=wuqi[i];
for(long long int j=temp.cost;j<=m;j++)
{
if(dp3[j-temp.cost]<dp2[j]+temp.atk)
{
dp3[j-temp.cost]=dp2[j]+temp.atk;
num[j-temp.cost]=i;
}
}
}
memcpy(dp4,dp3,sizeof(dp3));
for(long long int i=0;i<c;i++)
{
temp=wuqi[i];
for(long long int j=temp.cost;j<=m;j++)
{
if(i==num[j])
continue;
if(dp4[j-temp.cost]<dp3[j]+temp.atk)
dp4[j-temp.cost]=dp3[j]+temp.atk;
}
}
for(long long int i=0;i<d;i++)
{
temp=wuqi2[i];
for(long long int j=temp.cost;j<=m;j++)
{
if(dp4[j-temp.cost]<dp2[j]+temp.atk)
dp4[j-temp.cost]=dp2[j]+temp.atk;
}
}
long long int out=0;
for(long long int i=0;i<=m;i++)
out=max(out,dp4[i]);
cout << out << endl;

memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
memset(dp3,0,sizeof(dp3));
memset(dp4,0,sizeof(dp4));
memset(num,-1,sizeof(num));
memset(tou,0,sizeof(tou));
memset(shou,0,sizeof(shou));
memset(wuqi,0,sizeof(wuqi));
memset(wuqi2,0,sizeof(wuqi2));
}
return 0;
}


Problem C: wintermelon的魔界寻路之旅

原题。

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define inf 100000000
#define MOD 1000000009
#define MAXV 210

int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 };
//用于bfs和dfs搜索的方向
int map[MAXV][MAXV], vol[MAXV][MAXV], n, dis[MAXV][MAXV], flag[MAXV][MAXV], res;
//map保存网格,vol保存从0,0到i,j的最短路,n表示网格大小
//dis与flag用于深搜剪枝,res保存的是网格的最短路径

bool istrue(int x, int y){ //判断x,y是否是合理的,即不能超过界限
if (x < n && x >= 0 && y < n && y >= 0 && y < n - x) return true;
return false;
}

void dijstra(){
int x, y, tx, ty, i;
queue <int>q;

vol[0][0] = map[0][0];
q.push(0);
q.push(0);
while (!q.empty()){ //求出了所有0,0到i,j的最短路
x = q.front(); q.pop();
y = q.front(); q.pop();

for (i = 0; i<4; i++){
tx = x + dx[i];
ty = y + dy[i];
if (istrue(tx, ty) && vol[tx][ty]>map[tx][ty] + vol[x][y]){
q.push(tx);
q.push(ty);
vol[tx][ty] = map[tx][ty] + vol[x][y];
}
}
}
res = vol[0][n - 1];  //找出0,0到对称线上的最短路的最小值即是整个网格对称路径的最短路
for (i = 0; i<n; i++)
if (res>vol[i][n - i - 1]) res = vol[i][n - i - 1];
}

int dfs(int x, int y){
int i, tx, ty;
if (x == 0 && y == 0) return 1;

//这两句剪枝用的很巧妙,不加的话就会超时,表示x,y是否是第一次搜索,
//如果不是的话就直接返回,不用再次计算dis
//dis[x][y]表示从x,y到0,0有多少条这样的路径
if (flag[x][y]) return dis[x][y];
flag[x][y] = true;

dis[x][y] = 0;
for (i = 0; i < 4; i++){
tx = x + dx[i];
ty = y + dy[i];
if (istrue(tx, ty) && vol[x][y] == vol[tx][ty] + map[x][y]){
dis[x][y] = (dis[x][y] + dfs(tx, ty)) % MOD;
}
}
return dis[x][y];
}

int main(){
int i, j, key;
int t;
cin >> t;
while (t--)
{
scanf("%d", &n);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &map[i][j]);
//优化,把下三角的值加到上三角上面,这样就把问题看成从0,0到对称线上的最短路,可以减少很多计算量
for (i = 0; i < n; vol[i][j] = inf, i++)
for (j = 0; j < n - i - 1; j++){
map[i][j] = map[i][j] + map[n - j - 1][n - i - 1];
vol[i][j] = inf;
}

dijstra();  //求出了最短路

memset(flag, false, sizeof(flag));
key = 0;  //计算相等路有多少条
for (i = 0; i < n; i++)
if (res == vol[i][n - i - 1])
key = (key + dfs(i, n - i - 1)) % MOD;
printf("%d\n", key);

}

return 0;
}


Problem D: 二叉树的中序遍历

超级简单题却被坑了,连续俩#就绝对是错的。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std;
string str;
int t;
long long int l;
bool flag;
int last;
int now;
int main(void)
{
cin >> t;
while(t--)
{
cin >> str;
l=str.length();
flag=1;
last=0;
for(long long int i=0;i<l;i++)
{
if(str[i]=='#')
last++;
else
last=0;
if(last==2)
{
flag=0;
break;
}

}
if(flag)
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}


Problem E: 积木积水

水题

#include <iostream>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string.h>
#include <map>
#include <set>
using namespace std;

int T, N;
const int INF = 1000010;
int arr[INF];

int main(void){
cin >> T;
while(T --){
cin >> N;
long long ans = 0;
int MAXX;
for(int i= 0; i < N; i ++){
scanf("%d", &arr[i]);
if(i == 0){
MAXX = arr[i];
continue;
}
if(arr[i] <= MAXX){
ans += MAXX - arr[i];
}
else{
MAXX = arr[i];
}
}
int MINN = 0;
for(int i = N - 1; MINN != MAXX && i >= 0; i --){
if(i == N - 1){
MINN = arr[N - 1];
ans -= MAXX - MINN;
continue;
}
if(arr[i] <= MINN){
ans -= MAXX - MINN;
}
else{
MINN = arr[i];
ans -= MAXX - MINN;
}
}
cout << ans << endl;
}
}


Problem F: 我是好人4

看队友的吧- -

http://chilumanxi.org/2016/04/21/gdut-2016-%E6%A0%A1%E8%B5%9Bf-%E6%88%91%E6%98%AF%E5%A5%BD%E4%BA%BA4/

Problem G: 我是水题

真是水题。。。

#include <iostream>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string.h>
#include <map>
#include <set>
using namespace std;

int T;
int arr[1000];
int main(void){
cin >> T;
getchar();
while(T --){
memset(arr, 0, sizeof(arr));
int temp = 0;
string tempstr;
getline(cin, tempstr);
for(int i = 0; i < tempstr.size(); i ++){
if(tempstr[i] <= 'z' && tempstr[i] >= 'a'){
if(!arr[tempstr[i] - 'a']){
arr[tempstr[i] - 'a'] ++;
temp ++;
}

}
}
cout << temp << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: