[JSOI2009]游戏Game

Description

Input

输入数据首先输入两个整数N,M,表示了迷宫的边长。 接下来N行,每行M个字符,描述了迷宫。

Output

若小AA能够赢得游戏,则输出一行"WIN",然后输出所有可以赢得游戏的起始位置,按行优先顺序输出 每行一个,否则输出一行"LOSE"(不包含引号)。

Sample Input

3 3
.##
...
#.#

Sample Output

WIN
2 3
3 2

HINT

对于100%的数据,有1≤n,m≤100。 对于30%的数据,有1≤n,m≤5。

这道题和[NOI2011]兔兔与蛋蛋游戏很像

首先黑白染色

同样的,对于一个点,如果它不一定构成最大匹配

也就是ban掉该点后还有最大匹配

那么它就是后手必胜

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 struct Node
 8 {
 9   int next,to;
10 }edge[100001];
11 int head[10001],num,n,m,x,y,id[101][101],cnt,cx[10001],tot;
12 bool vis[10001];
13 char s[1001];
14 void add(int u,int v)
15 {
16   num++;
17   edge[num].next=head[u];
18   head[u]=num;
19   edge[num].to=v;
20 }
21 bool dfs(int x)
22 {int i;
23   for (i=head[x];i;i=edge[i].next)
24     {
25       int v=edge[i].to;
26       if (vis[v]==0)
27     {
28       vis[v]=1;
29       if (!cx[v]||dfs(cx[v]))
30         {
31           cx[x]=v;cx[v]=x;
32           return 1;
33         }
34     }
35     }
36   return 0;
37 }
38 int main()
39 {int i,j,flag=0;
40   cin>>n>>m;
41   for (i=1;i<=n;i++)
42     {
43       scanf("%s",s+1);
44       for (j=1;j<=m;j++)
45     {
46       if (s[j]=='.') id[i][j]=++cnt;
47     }
48     }
49   for (i=1;i<=n;i++)
50     {
51       for (j=1;j<=m;j++)
52     if (id[i][j])
53       {
54         if (i>1&&id[i-1][j]) add(id[i][j],id[i-1][j]);
55         if (i<n&&id[i+1][j]) add(id[i][j],id[i+1][j]);
56         if (j>1&&id[i][j-1]) add(id[i][j],id[i][j-1]);
57         if (j<m&&id[i][j+1]) add(id[i][j],id[i][j+1]);
58       }
59     }
60   for (i=1;i<=n;i++)
61     {
62       for (j=1;j<=m;j++)
63     if (id[i][j]&&(i+j)%2)
64       {
65         memset(vis,0,sizeof(vis));
66         dfs(id[i][j]);
67       }
68     }
69   for (i=1;i<=n;i++)
70     {
71       for (j=1;j<=m;j++)
72     if (id[i][j])
73     {
74           memset(vis,0,sizeof(vis));
75           int u=id[i][j],v=cx[id[i][j]];
76            vis[u]=1;
77           if (!cx[u]||dfs(v))
78         {
79           cx[u]=0;
80           if (flag==0)
81             cout<<"WIN\n";
82           flag=1;
83           printf("%d %d\n",i,j);
84         }
85     }
86     }
87   if (flag==0) cout<<"LOSE";
88 }

 

转载于:https://www.cnblogs.com/Y-E-T-I/p/8202473.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用[1],dp[u][j]表示在u子树中选取恰好j个人时能获得的最大价值。而根据引用,该问题的时间复杂度为O(log2​104×nm)。 对于洛谷P2143 [JSOI2010] 巨额奖金问题,我们可以使用动态规划来解决。具体步骤如下: 1. 首先,我们需要构建一棵树来表示员工之间的关系。树的根节点表示公司的总经理,其他节点表示员工。每个节点都有一个权值,表示该员工的奖金金额。 2. 接下来,我们可以使用动态规划来计算每个节点的dp值。对于每个节点u,我们可以考虑两种情况: - 如果选择节点u,则dp[u][j] = dp[v][j-1] + value[u],其中v是u的子节点,value[u]表示节点u的奖金金额。 - 如果不选择节点u,则dp[u][j] = max(dp[v][j]),其中v是u的子节点。 3. 最后,我们可以通过遍历树的所有节点,计算出dp[u][j]的最大值,即为所求的巨额奖金。 下面是一个示例代码,演示了如何使用动态规划来解决洛谷P2143 [JSOI2010] 巨额奖金问题: ```python # 构建树的数据结构 class Node: def __init__(self, value): self.value = value self.children = [] # 动态规划求解最大奖金 def max_bonus(root, j): dp = [[0] * (j+1) for _ in range(len(root)+1)] def dfs(node): if not node: return for child in node.children: dfs(child) for k in range(j, 0, -1): dp[node.value][k] = max(dp[node.value][k], dp[node.value][k-1] + node.value) for child in node.children: for k in range(j, 0, -1): for l in range(k-1, -1, -1): dp[node.value][k] = max(dp[node.value][k], dp[node.value][k-l-1] + dp[child.value][l]) dfs(root) return dp[root.value][j] # 构建树 root = Node(1) root.children.append(Node(2)) root.children.append(Node(3)) root.children[0].children.append(Node(4)) root.children[0].children.append(Node(5)) root.children[1].children.append(Node(6)) # 求解最大奖金 j = 3 max_bonus_value = max_bonus(root, j) print("最大奖金为:", max_bonus_value) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值