水水的DFS

原题http://acm.hdu.edu.cn/showproblem.php?pid=4536

XCOM Enemy Unknown

Time Limit: 500/200 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 851    Accepted Submission(s): 257

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   |   We have carefully selected several similar problems for you: 
4919 4918 4917 4916 4915

//这道题目很明显是要用沈搜,由于数据都不是很大,所以最后的时间是0秒
//具体的操作过程是每次都要枚举所有的情况。如果满足则继续深搜下去,如果不满足,则将那些值都还原。要主要搜索最后结束的 条件
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#include <string>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define N 20
#define M 100 + 10
int attack[M][3];
int num[N];
int sum[N];
int n,m,k;
int max_cn;

int max(int a,int b){
	return a>b?a:b;
}

void DFS(int cn){
	int i;
	if(cn >= k){//这种情况是因为如果第一次就可以一直搜下去到最后
		max_cn = k;
		return ;
	}
	if(max_cn >= k){//满了。就结束搜索
		//max_cn = k;
		return ;
	}
	int a[3];
	int b[3];
	int j;
	for(i=0;i<3;i++){
		a[0] = attack[cn][i];//救助的国家的编号
		a[1] = attack[cn][(i+1)%3];//其余两个国家的编号
		a[2] = attack[cn][(i+2)%3];
		b[0] = sum[a[0]];//先保存下来这三个国家的值
		b[1] = sum[a[1]];
		b[2] = sum[a[2]];
		sum[a[0]]= sum[a[0]]-2;
		if(sum[a[0]] < 1){
			sum[a[0]] = 1;
		}
		sum[a[1]]+=2;
		sum[a[2]]+=2;
		for(j=0;j<n;j++){
			if(num[j]==num[a[1]] && j!=a[1]){
				sum[j]++;
			}
			if(num[j]==num[a[2]] && j!=a[2]){
				sum[j]++;
			}
		}
		int flag = 1;
		for(j=0;j<n;j++){
			if(sum[j] > 5){//如果有大于5的情况就说明不能继续进行下去了
				max_cn = max(cn,max_cn);//记录下当前最大的值
				flag = 0;
			}
		}
		if(flag == 1){//如果可以,则继续搜索下去
			DFS(cn+1);
		}
		//还原
		sum[a[0]] = b[0];
		sum[a[1]] = b[1];
		sum[a[2]] = b[2];
		for(j=0;j<n;j++){
			if(num[j]==num[a[1]] && j!=a[1]){
				sum[j]--;
			}
			if(num[j]==num[a[2]] && j!=a[2]){
				sum[j]--;
			}
		}
	}
}

int main(){
	int T;
	int cas,i;

	while(~scanf("%d",&T)){
		memset(num,0,sizeof(num));
		memset(sum,0,sizeof(sum));
		memset(attack,0,sizeof(attack));
		for(cas=1;cas<=T;cas++){
			scanf("%d%d%d",&n,&m,&k);
			for(i=0;i<n;i++){
				scanf("%d",&num[i]);
			}
			for(i=0;i<n;i++){
				scanf("%d",&sum[i]);
			}
			for(i=0;i<k;i++){
				scanf("%d%d%d",&attack[i][0],&attack[i][1],&attack[i][2]);
			}
			max_cn = 0;
			//printf("Case #%d: %d",cas);
			DFS(0);
			printf("Case #%d: %d\n",cas,max_cn);
		}
	}

	return 0;
}

水水的DFS

时间: 2024-08-29 09:21:11

水水的DFS的相关文章

hust 1377 - Sequence

题目描述 Given a number sequence whose length is n, you can delete at most k numbers in the sequence.After that you are asked to answer the maximum length of longest continuous subsequence that each number in it is larger than its previous number(if has

HDU 5305 Friends

水水的DFS 题意:n个人m个关系,要求每个人的网上朋友和现实朋友一样多,求一共有多少种关系 解:因为数据小,暴力DFS就可以了,不过要一点小剪枝 #include <stdio.h> #include <string.h> int point[10]; struct aaa { int x,y; }line[30]; struct bbb { int online,outline; }node[10]; int sum; void dfs(int n,int m,int p) {

HLG2179 组合(dfs水水更健康)

组合 Time Limit: 1000 MS Memory Limit: 32768 K Total Submit: 57(38 users) Total Accepted: 43(36 users) Rating: Special Judge: No Description 给出一个正整数N,从集合{1,2,3..N} 中找出所有大小为k的子集, 并按照字典序从小到大输出. Input 第一行是一个整数T,代表T组测试数据. 接下来T行,每行是两个正整数n(1<=n<=10), k(1<

ZOJ 题目2100 Seeding(DFS)

Seeding Time Limit: 2 Seconds      Memory Limit: 65536 KB It is spring time and farmers have to plant seeds in the field. Tom has a nice field, which is a rectangle with n * m squares. There are big stones in some of the squares. Tom has a seeding-ma

解救小哈——DFS算法举例

一.问题引入 有一天,小哈一个人去玩迷宫.但是方向感不好的小哈很快就迷路了.小哼得知后便去解救无助的小哈.此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈.那么,问题来了... 二.问题的分析 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向. 在这里我们规定一

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

uva1103(dfs)

UVA - 1103 还是没写好,,看的别人的 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <stack> 8 #include <cctype> 9 #include <str

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

蓝桥杯 大臣的旅费_树的最长度_两次DFS

#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <functional> #include <vector> using namespace std; const int maxn = 1000000 + 10; const int INF = 10000000