您的位置:首页 > 其它

【组队补题题】The Seventh Hunan Collegiate Programming Contest Semilive

2016-03-27 22:39 381 查看
题目链接:点击打开链接

B 【UVA 12290】
Counting Game



D 【UVA 12292】
Polyomino Decomposer


将给出的图形中的*按照顺序标记,枚举状态,然后判断这个状态是否可行

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int>pii;
int n;
char s[15][15], a[15][15];
int px[25], py[25], num, cnt, xi, yi;
int vis[25][25], dir[4][2]={0,1,1,0,0,-1,-1,0};
int vm[15][15], tot;
char cc[15][15];
queue<pii>q;
struct node
{
int x, y;
}id[25];
int bfs()
{
while(!q.empty()) q.pop();
q.push(make_pair(xi, yi));
int tmp=1;
id[tmp-1].x=xi, id[tmp-1].y=yi;
while(!q.empty())
{
pii u = q.front(); q.pop();
vis[u.first][u.second]=0;
for(int i=0; i<4; i++)
{
int xx=u.first+dir[i][0], yy=u.second+dir[i][1];
if(xx<0 || xx>=n || yy<0 || yy>=n) continue;
if(vis[xx][yy]==0) continue;
if(s[xx][yy]=='.') continue;
vis[xx][yy]=0, tmp++, q.push(make_pair(xx, yy));
id[tmp-1].x=xx, id[tmp-1].y=yy;
}
}
return tmp;
}
void check(int xx, int yy)
{
int len=-1;
memset(vm, 0, sizeof(vm));
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cc[i][j] = a[i][j];
}
}
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
if(s[i][j]=='*' && vm[i][j]==0)
{
len++, xx=i, yy=j;
cc[i][j]='A'+len, vm[i][j]=1;
for(int k=1; k<num; k++){
int cx=id[k].x-id[k-1].x;
int cy=id[k].y-id[k-1].y;
xx+=cx, yy+=cy;
if(xx<0 || xx>=n || yy<0 || yy>=n) return;
if(vm[xx][yy]) return;
if(s[xx][yy]=='.') return;
vm[xx][yy]=1, cc[xx][yy]='A'+len;
}
}

}
}
if(tot==-1 || tot>len+1){//tot:给出的图形可以由tot个基本图形组成,tot越小,字典序越小
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
a[i][j] = cc[i][j];
}
}
tot=len+1;
}
return;
}
int main()
{
while(~scanf("%d", &n))
{
if(n==0) break;
xi=yi=-1, cnt=0, tot=-1;
for(int i=0; i<n; i++){
scanf("%s",   s[i]);
for(int j=0; j<n; j++){
if(s[i][j]=='*')
{
a[i][j]='A'+cnt;
px[cnt]=i, py[cnt]=j, cnt++;
if(xi==-1) xi=i, yi=j;
}
else a[i][j]='.';
}
a[i]
='\0';
}
for(int i=3; i<(1<<cnt); i+=2)
{
if(i&1)
{
num=1;
bool flag;
memset(vis, 0, sizeof(vis));
for(int j=1; (1<<j)<=i; j++)
{
int sss = 1<<j;
if(sss&i)
{
vis[px[j]][py[j]]=1;
num++;
}
}
if(cnt%num || cnt==num) continue;
if(num == bfs()) flag=true;//bfs检验这num个点是不是相邻的
else flag=false;
if(flag) check(xi, yi);//验证给出的图形能不能由这num个点组成
}
}
for(int i=0; i<n; i++) printf("%s\n", a[i]);
printf("\n");
}
return 0;
}

E 【UVA 12293】Box Game(博弈,找规律)
2 先手必胜

3 先手必败

4 5 6 先手必胜

7 先手必败

8 9 10 11 12 13 14 先手必胜

15 先手必败……

如果面对的情况是:在(n+1)/2 ~n-1中存在先手必败点,这种情况是先手必胜,否则先手必败

分析数据就会发现只有n=2^x-1时先手必败

#include <bits/stdc++.h>
using namespace std;
int a[30];
void init()
{
int ans=1;
for(int i=1; i<30; i++)
{
ans*=2;
a[i]=ans;
}
}
int main()
{
int n;
init();
while(scanf("%d", &n))
{
if(n==0) break;
int flag=0, ans=1;
for(int i=1; i<30; i++)
{
if(n==a[i]-1) flag=1;
}
if(flag) printf("Bob\n");
else printf("Alice\n");
}
return 0;
}



F 【UVA 12294】
RPG battles


题意:玩游戏,一开始有p(1<=p<=100)能量,有n(1<=n<=1000)个怪,每个怪有六种指标,p1、p2、t1、t2、w1、w2(1<=p1<p1<=100,1<=t2<t1<=100,0<=w1,w2<=10),打每个怪的时间计算方式是:t1-(p-p1)*(t2-t1)/(p2-p1),当然如果p小于p1,不能打死怪物,输出Impossible,如果p大于p2,时间就是t2。每打死一只怪就能得到奖励技能牌,一类牌w1张,二类牌w2张,一类牌可以将能量值+1,二类牌可以将能量值翻倍,每次可以将奖励牌用完或者不用或用掉部分,怪只能按照顺序一个一个打,一开始手里没有技能牌问最后要是能将所有的怪打死最少需要多少时间?

解题思路:能量值最大都是100,并且能量值越大,杀怪的时间越少,所以我们要在不影响结果的情况下让能量值尽可能的大,那么一类牌遇到一张用掉一张,利用两个优先队列队列枚举每次用的二类牌的张数,输出最少时间。

#include <bits/stdc++.h>
using namespace std;
struct node
{
int  wi;
double pi,time;
friend bool operator < (const node n1, const node n2)
{
return n1.time > n2.time;
}
}s, e;
int a[10];
void init()
{
int ans=1;
a[0]=1;
for(int i=1; i<=10; i++)
{
ans*=2;
a[i] = ans;
}
}
priority_queue<node>q[2];
int main()
{
init();
int n;
double m;
double p, pp, t, tt;
int w, ww;
while(~scanf("%d%lf", &n, &m))
{
if(n==0 && m==0) break;
while(!q[0].empty()) q[0].pop();
while(!q[1].empty()) q[1].pop();
scanf("%lf%lf%lf%lf%d%d", &p, &pp, &t, &tt, &w, &ww);
int f=1, ff=0, flag=0;
if(m<p) flag=1;
else{
s.pi=m, s.wi=ww;
if(s.pi>pp) s.time=tt;
else s.time=t-(t-tt)*(s.pi-p)/(pp-p);
if(w) s.pi+=w;
q[0].push(s);
}
for(int i=1; i<n; i++)
{
scanf("%lf%lf%lf%lf%d%d", &p, &pp, &t, &tt, &w, &ww);
if(flag) continue;
int vv=0;
while(!q[ff].empty())
{
s=q[ff].top(); q[ff].pop();
for(int i=0; i<=s.wi; i++)
{
e.pi=s.pi*a[i];
if(e.pi<p) continue;
else if(e.pi>pp) e.time=s.time+tt;
else e.time=s.time+t-(t-tt)*(e.pi-p)/(pp-p);
e.wi=s.wi-i+ww;
if(w) e.pi+=w;
q[f].push(e);
vv=1;
if(e.pi-w>=100) break;
}
}
if(vv==0) flag=1;
swap(ff, f);
}
if(flag) printf("Impossible\n");
else printf("%.2lf\n", q[ff].top().time);
}
return 0;
}


G 【UVA 12295】Optimal Symmetric Paths(建图&&最短路&&搜索)

题意:一个n*n的棋盘,每格棋盘上都有一个数字,求从(1,1)开始走到(n,n)路径的条数(可以往上下左右四个方向走),路径满足以下条件:1、关于对角线对称 2、路径上的所有点的和最小

解题思路:将对角线下方的方格里的值加到对角线上方,从(0, 0)开始找到一条通向对角线的路,那么这条路上的和就是从(0, 0)走到(n-1, n-1),并且路线关于对角线对称。点(i, j)记为第i*n+j个点。建图,将相邻两点连通,用最短路算法求出从起始点到对角线上方的点的最短距离,同时用vector容器fa[v]来记录到能到点v的点,从对角线dis最小的点开始反向搜路径条数。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+9;
const int N=150;
const int maxm=3e5;
int n, a

;
int head[maxm], dir[4][2]={0,1,1,0,0,-1,-1,0};
queue<int>q;
vector<int>fa[maxm];
int to[maxm], w[maxm], nxt[maxm];
int tot, dis[maxm];
ll dp[maxm];
bool vis[maxm];
void init()
{
memset(head, -1, sizeof(head));
tot=0;
while(!q.empty()) q.pop();
memset(dis, 0x3f3f3f3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
for(int i=0; i<maxm; i++) fa[i].clear();
memset(dp, 0, sizeof(dp));
}

void input()
{
for(int i=0; i<n; i++){
for(int j=0; j<n; j++) scanf("%d", &a[i][j]);
}
for(int i=0; i<n-1; i++){
for(int j=0; j<n-i-1; j++){
a[i][j]+=a[n-1-j][n-i-1];
}
}
}

void addedge(int u, int v, int wi)
{
to[tot]=v, nxt[tot]=head[u], w[tot]=wi, head[u]=tot++;
}
void BuildGraph()
{
for(int i=0; i<n-1; i++){
for(int j=0; j<n-i-1; j++){
for(int k=0; k<4; k++){
int xi=i+dir[k][0];
int yi=j+dir[k][1];
if(xi<0||xi>=n||yi<0||yi>=n) continue;
int u=i*n+j, v=xi*n+yi;
addedge(u, v, a[xi][yi]);
}
}
}
}
void spfa()
{
int u=0, v, wi;
q.push(u);
vis[u]=1, dis[u]=0;
while(!q.empty())
{
u=q.front(); q.pop();
vis[u]=false;
for(int i=head[u]; i!=-1; i=nxt[i])
{
v=to[i], wi=w[i];
if(dis[v]==dis[u]+wi)
{
fa[v].push_back(u);
}
if(dis[v]>dis[u]+wi)
{
fa[v].clear();
dis[v]=dis[u]+wi;
fa[v].push_back(u);
if(!vis[v]) vis[v]=true, q.push(v);
}

}
}
}

ll dfs(int u)
{
if(u==0) dp[u]=1;
ll ret=0;
if(dp[u]) return dp[u];
for(int i=0; i<fa[u].size(); i++){
ret = (ret+dfs(fa[u][i]))%mod;
}
return dp[u]=ret;
}

int main()
{
while(~scanf("%d", &n))
{
if(n==0) break;
init();
input();
BuildGraph();
spfa();
int minx=0x3f3f3f3f;
for(int i=0; i<n; i++) {
int j=n-1-i;
minx = min(minx, dis[i*n+j]);
}
ll ans=0;
for(int i=0; i<n; i++)
{
int j=n-1-i;
if(dis[i*n+j]==minx) {
ans = (ans+dfs(i*n+j))%mod;
}
}
printf("%d\n", ans);
}
return 0;
}/*2
1 1
1 1
3
1 1 1
1 1 1
2 1 1*/


H 【UVA 12296】
Pieces and Discs

I  【UVA 12297】Super Poker

J 【UVA 12298】 Super Poker II

K 【UVA 12299】 RMQ with Shifts
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: