HDU 4536 XCOM Enemy Unknown ( 状态压缩+搜索)

XCOM Enemy Unknown

Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 133    Accepted Submission(s): 34

Problem Description XCOM-Enemy Unknown是一款很好玩很经典的策略游戏.

在游戏中,由于未知的敌人–外星人入侵,你团结了世界各大国家进行抵抗.

随着游戏进展,会有很多的外星人进攻事件.每次进攻外星人会选择3个国家攻击,作为联盟的指挥者,你要安排有限的联盟军去支援其中一个国家,抵抗进攻这个国家的外星人.

战斗胜利之后这个被支援的国家恐慌值就会-2点
(恐慌值最少减为1),而其他两个未被支援的国家恐慌值就会+2点,同时和这两个国家在相同大洲的其他国家恐慌值也会+1点.

当一个国家的恐慌值超过5点,这个国家就会对联盟失去信心从而退出联盟.

现在给你外星人将会进攻的地点,问你最多能在不失去任何一个国家信任的情况下抵挡多少次外星人的进攻.  

 

Input 第一行有一个整数T代表接下来有T组数据

每组数据第一行是三个整数,n,m,k分别代表联盟国家的个数,大洲的个数,外星人的进攻次数.

第二行是n个数字代表各个国家所属的大洲(大洲序号从0到m-1)

第三行是n个数字代表各个国家初始的恐慌值

接下去k行代表外星人进攻

每行有三个数字,表示该次外星人进攻的国家(国家序号从0到n-1)

[Technical Specification]

0<T<=100

8<n<=16

2<m<=5

0<k<=100

0<初始恐慌值<=5

每个州至少有三个国家

每次外星人进攻一定发生在不同州的三个国家  

 

Output 首先输出case数(见sample),接着输出在不失去任何一个国家的情况下能抵挡外星人进攻最多的次数.  

 

Sample Input 1 9 3 2 0 0 0 1 1 1 2 2 2 3 3 3 3 3 3 3 3 3 0 3 6 0 3 6  

 

Sample Output Case #1: 1
Hint 第一次如果选择了0,那么3和6的恐慌值就会增加到5,第二次不管怎么选择,3和6总会有一个超过5.  

 

Source
2013腾讯编程马拉松复赛第二场(3月30日)  

 

Recommend liuyiding

 

 

 

直接搜索的。

用二进制进行压缩,3为二进制表示一个。用long long

 

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
#include <set>
#include <queue>
#include <math.h>
using namespace std;

int a[20];
int b[20];

int x[100],y[100],z[100];
int ans;
int n,m,k;

long long change1(int t[])
{
    long long temp=0;
    for(int i=0;i<n;i++)
    {
        temp<<=3;
        temp|=t[i];
    }
    return temp;
}
void change2(int t[],long long p)
{
    for(int i=n-1;i>=0;i--)
    {
        t[i]=p&7;
        p>>=3;
    }
}

void dfs(long long state,int t)
{
    ans=max(ans,t);
    if(t>=k)return;
    long long temp;
    bool flag;

    change2(a,state);
    a[x[t]]-=2;
    if(a[x[t]]<1)a[x[t]]=1;

    a[y[t]]+=1;
    a[z[t]]+=1;
    for(int i=0;i<n;i++)
      if(i!=x[t] && (b[y[t]]==b[i]||b[z[t]]==b[i]))
        a[i]++;
    flag=true;
    for(int i=0;i<n;i++)
      if(a[i]>5)
      {
          flag=false;
          break;
      }
    if(flag)
    {
        long long temp=change1(a);
        dfs(temp,t+1);
    }

    change2(a,state);
    a[y[t]]-=2;
    if(a[y[t]]<1)a[y[t]]=1;

    a[x[t]]+=1;
    a[z[t]]+=1;
    for(int i=0;i<n;i++)
      if(i!=y[t] && (b[x[t]]==b[i]||b[z[t]]==b[i]))
        a[i]++;
    flag=true;
    for(int i=0;i<n;i++)
      if(a[i]>5)
      {
          flag=false;
          break;
      }
    if(flag)
    {
        long long temp=change1(a);
        dfs(temp,t+1);
    }

    change2(a,state);
    a[z[t]]-=2;
    if(a[z[t]]<1)a[z[t]]=1;

    a[y[t]]+=1;
    a[x[t]]+=1;
    for(int i=0;i<n;i++)
      if(i!=z[t] && (b[y[t]]==b[i]||b[x[t]]==b[i]))
        a[i]++;
    flag=true;
    for(int i=0;i<n;i++)
      if(a[i]>5)
      {
          flag=false;
          break;
      }
    if(flag)
    {
        long long temp=change1(a);
        dfs(temp,t+1);
    }


}

int main()
{
    int T;
    scanf("%d",&T);
    int iCase=0;
    while(T--)
    {
        iCase++;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<n;i++)
          scanf("%d",&b[i]);
        for(int i=0;i<n;i++)
          scanf("%d",&a[i]);
        for(int i=0;i<k;i++)
          scanf("%d%d%d",&x[i],&y[i],&z[i]);
        ans=0;

        long long tmp=change1(a);

        dfs(tmp,0);

        printf("Case #%d: %d\n",iCase,ans);
    }
    return 0;
}

 

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/archive/2013/03/30/2991053.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞