当初没做出来的题,被3^100 复杂度吓到了。其实就是裸搜, 可以证明十几次进攻后就会结束。
解法:水DFS
代码:
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<set>
using namespace std;
const int maxn = 200;
int zhou[20];
int kong[20];
bool vis[20];
vector<int> v[10];
int step[110][3];
int t, n, m, k, ans;
void init()
{
memset(step, 0, sizeof step);
memset(kong, 0, sizeof kong);
for(int i = 0 ; i < 10; ++ i) v[i].clear();
ans = 0;
}
void dfs(int s)
{
ans = max(ans, s);
if(s==k) return;
for(int i = 0 ; i < 3 ; ++ i)
{
int a = step[s][i], b = step[s][(i+1)%3], c = step[s][(i+2)%3];
int tmpkong[20];
for(int i = 0 ; i < n ; ++ i) tmpkong[i] = kong[i];
kong[a] -= 2; kong[b]+= 2; kong[c]+= 2;
memset(vis, true, sizeof vis);
bool flag = true;
vis[a] = vis[b] = vis[c] = false;
int tmp = zhou[b];
for(int i = 0 ; i < v[tmp].size() ; ++ i)
{
if(!vis[v[tmp][i]]) continue;
vis[v[tmp][i]] = false;
kong[v[tmp][i]]++;
}
tmp = zhou[c];
for(int i = 0 ; i < v[tmp].size() ; ++ i)
{
if(!vis[v[tmp][i]]) continue;
vis[v[tmp][i]] = false;
kong[v[tmp][i]]++;
}
for(int i = 0 ; i < n ; ++ i)
{
if(kong[i]>5) flag = false;
if(kong[i]<1) kong[i] = 1;
}
if(flag) dfs(s+1);
for(int i = 0 ; i < n ; ++ i) kong[i] = tmpkong[i];
}
}
int main()
{
//freopen("in.txt","r",stdin);
int t; scanf("%d", &t);
int kase = 1;
while(t--)
{
init();
scanf("%d%d%d", &n, &m, &k);
for(int i = 0 ; i < n ; ++ i)
{
int z; scanf("%d", &z);
zhou[i] = z;
v[z].push_back(i);
}
for(int i = 0 ; i < n ; ++ i)
{
int z; scanf("%d", &z);
kong[i] = z;
}
for(int i = 0 ; i < k ; ++ i)
{
int a, b, c; scanf("%d%d%d", &a, &b, &c);
step[i][0] = a;
step[i][1] = b;
step[i][2] = c;
}
dfs(0);
printf("Case #%d: %d\n", kase++, ans);
}
return 0;
}