【組隊補題題】The Seventh Hunan Collegiate Programming Contest Semilive

題目鏈接:點擊打開鏈接

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][n]='\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)個怪,每個怪有六種指標,p1p2t1t2w1w2(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[N][N];
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 12297Super Poker


J 【UVA 12298】 Super Poker II


K 【UVA 12299】 RMQ with Shifts

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章