poj 1085 Triangle War (状压+记忆化搜索)


Triangle War

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 2685   Accepted: 1061

Description

Triangle War is a two-player game played on the following triangular grid:

Two players, A and B, take turns filling in any dotted line connecting two dots, with A starting first. Once a line is filled, it cannot be filled again. If the line filled by a player completes one or more triangles, she owns the completed triangles and she
is awarded another turn (i.e. the opponent skips a turn). The game ends after all dotted lines are filled in, and the player with the most triangles wins the game. The difference in the number of triangles owned by the two players is not important.

For example, if A fills in the line between 2 and 5 in the partial game on the left below:

Then, she owns the triangle labelled A and takes another turn to fill in the line between 3 and 5. B can now own 3 triangles (if he wishes) by filling in the line between 2 and 3, then the one between 5 and 6, and finally the one between 6 and 9. B would then
make one more move before it is A‘s turn again.

In this problem, you are given a number of moves that have already been made. From the partial game, you should determine which player will win assuming that each player plays a perfect game from that point on. That is, assume that each player always chooses
the play that leads to the best possible outcome for himself/herself.

Input

You will be given a number of games in the input. The first line of input is a positive integer indicating the number of games to follow. Each game starts with an integer 6 <= m <= 18 indicating the number of moves that have been made in the game. The next
m lines indicate the moves made by the two players in order, each of the form i j (with i < j) indicating that the line between i and j is filled in that move. You may assume that all given moves are legal.

Output

For each game, print the game number and the result on one line as shown below. If A wins, print the sentence "A wins." If B wins, print "B wins."

Sample Input

4
6
2 4
4 5
5 9
3 6
2 5
3 5
7
2 4
4 5
5 9
3 6
2 5
3 5
7 8
6
1 2
2 3
1 3
2 4
2 5
4 5
10
1 2
2 5
3 6
5 8
4 7
6 10
2 4
4 5
4 8
7 8 

Sample Output

Game 1: B wins.
Game 2: A wins.
Game 3: A wins.
Game 4: B wins.

Source

East Central North America 1999

题意:

两个人玩游戏,依次在三角形上放边,如果能构成三角形,则奖励继续该此人放,问最后得到的三角形多。

思路:

给边编号,记忆化搜索就行,做过好多这种题,就不多写思路了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 50005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;

int n,m,ans,cnt,tot,flag;
bool vis[10];
int dp[300000],mp[15][15],sc[5];
int tri[9][3]=
{
    0,1,2,3,4,7,2,4,5,5,6,8,9,10,15,
    7,10,11,11,12,16,8,12,13,13,14,17
};

int cal(int s)
{
    int i,j,t=0;
    for(j=0; j<9; j++)
    {
        if((s&(1<<tri[j][0]))&&(s&(1<<tri[j][1]))&&(s&(1<<tri[j][2]))) t++;
    }
    return t;
}
int dfs(int state,int score)
{
    if(dp[state]!=-1) return dp[state];
    int i,j,t,tst,num,best=0,tmp;
    num=9-score;
    for(i=0; i<=17; i++)
    {
        if(state&(1<<i)) continue ;
        tst=state|(1<<i);
        t=cal(tst);
        if(t>num)
        {
            tmp=t-num+dfs(tst,score-(t-num));
            best=max(best,tmp);
        }
        else
        {
            tmp=score-dfs(tst,score);
            best=max(best,tmp);
        }
    }
    dp[state]=best;
    return best;
}
int main()
{
    int i,j,t,test=0;
    mp[1][2]=0;mp[1][3]=1;mp[2][3]=2;mp[2][4]=3;mp[2][5]=4;mp[3][5]=5;
    mp[3][6]=6;mp[4][5]=7;mp[5][6]=8;mp[4][7]=9;mp[4][8]=10;mp[5][8]=11;
    mp[5][9]=12;mp[6][9]=13;mp[6][10]=14;mp[7][8]=15;mp[8][9]=16;mp[9][10]=17;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        tot=0;
        int x,y,z,turn=0,num=0;
        sc[0]=sc[1]=0;
        memset(vis,0,sizeof(vis));
        for(i=1; i<=n; i++)
        {
            scanf("%d%d",&x,&y);
            z=mp[x][y];
            tot|=(1<<z);
            flag=0;
            for(j=0; j<9; j++)
            {
                if(vis[j]) continue ;
                if((tot&(1<<tri[j][0]))&&(tot&(1<<tri[j][1]))&&(tot&(1<<tri[j][2])))
                {
                    vis[j]=1;
                    num++;
                    flag=1;
                    sc[turn]++;
                }
            }
            if(!flag) turn^=1;
        }
        memset(dp,-1,sizeof(dp));
        z=dfs(tot,9-num);
        sc[turn]+=z;
        sc[turn^1]+=(9-num-z);
        if(sc[0]>sc[1]) printf("Game %d: A wins.\n",++test);
        else printf("Game %d: B wins.\n",++test);
    }
    return 0;
}

poj 1085 Triangle War (状压+记忆化搜索)

时间: 2024-12-17 00:01:25

poj 1085 Triangle War (状压+记忆化搜索)的相关文章

POJ 2704 Pascal&#39;s Travels (基础记忆化搜索)

Pascal's Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5328   Accepted: 2396 Description An n x n game board is populated with integers, one nonnegative integer per square. The goal is to travel along any legitimate path from t

POJ 1579 Function Run Fun 【记忆化搜索入门】

题目传送门:http://poj.org/problem?id=1579 Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20560   Accepted: 10325 Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <=

(中等) POJ 1054 The Troublesome Frog,记忆化搜索。

Description In Korea, the naughtiness of the cheonggaeguri, a small frog, is legendary. This is a well-deserved reputation, because the frogs jump through your rice paddy at night, flattening rice plants. In the morning, after noting which plants hav

poj 1088 滑雪(区间dp+记忆化搜索)

题目链接:http://poj.org/problem?id=1088 思路分析: 1>状态定义:状态dp[i][j]表示在位置map[i][j]可以滑雪的最长区域长度: 2>状态转移方程:由于由位置[i, j]只能向四个方向移动,所以子问题最多有四个:所以dp[i][j]为其邻域可以滑雪的最大区域长度加上从该位置滑到邻域的长度,即1: 代码如下: #include <cstdio> #include <iostream> #include <algorithm&

POJ 1088: 滑雪(经典 DP+记忆化搜索)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 74996   Accepted: 27818 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

HDU 4778 记忆化搜索&amp;状压

给出G种宝石,B个包,和S,S代表到时候每种颜色的宝石凑齐S个能变成一个魔法石 每个包里有N种宝石,分别为c1,c2....... 然后两人轮流拿包,每个包只能拿一次,拿出包把宝石放地上. 如果能变成魔法石则拿走魔法石,下一次还这个人拿包,没变成则换人. 魔法石的个数就是获得分数,问两人最优的时候分差是多少. 状压记忆化搜索 一共21个包,状压存当前取包的状态 无论怎样取,最后获得的魔法石数量一定 dp[i]表示在i状态下,先手可以获得的最高分数 #include "stdio.h"

POJ 1088 滑雪(记忆化搜索)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 92384   Accepted: 34948 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还