我的暴力dfs超时了,看了官方题解写了状压dp.
官方题解是正向延伸dp的。
我的是"从后往前确认"dp的。
另外预处理我没有做排序,而是直接暴力匹配的。
目录
状压dp:
vector<string>genres;
vector<string>writers;
int n;
int gsame[17][17];
int wsame[17][17];
int bitcnt(unsigned aim)
{
int ret = 0;
while (aim)
{
if (aim & 1)
ret++;
aim >>= 1;
}
return ret;
}
void solve()
{
memset( gsame,0,sizeof gsame );
memset( wsame,0,sizeof wsame );
cin >> n;
genres = writers = vector<string>(n);
for (int i = 0; i < n; i++)
{
cin >> genres[i] >> writers[i];
}
//预处理字符串是否相等
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
if (genres[i] == genres[j])
gsame[i][j] = gsame[j][i] = 1;
if (writers[i] == writers[j])
wsame[i][j] = wsame[j][i] = 1;
}
}
//一维是状态,二维是此刻尾部是第几个,dp为1代表这种状态可取
vector<vector<int>>dp(1<<n, vector<int>(n));
//初始化
for (int i = 0; i < n; i++)
{
dp[1 << i][i] = 1;
}
//遍历所有情况
for (int mask = 0; mask < (1 << n); mask++)
{
for (int i = 0; i < n; i++)
{
if (mask >> i&1)
{
int lastm = mask - (1 << i);
for (int j = 0; j < n; j++)
{
if (lastm >> j&1)
{
if (dp[lastm][j] == 1&&(gsame[i][j] || wsame[i][j]))
{
dp[mask][i] = 1;
break;
}
}
}
//if (dp[mask][i])break;每个合法的i都要测试到
}
}
}
int ans = 0;
for (int mask = 0; mask < (1 << n); mask++)
for (int i = 0; i < n; i++)
if (dp[mask][i])
ans = max(ans, bitcnt(mask));
cout << n - ans << endl;
}
剪枝的dfs:
vector<string>genres;
vector<string>writers;
int ans;
int vis[17];
int mem[1 << 16][16];//剪枝
int n;
int gsame[17][17];
int wsame[17][17];
void dfs(int aim, int cur,int mask)
{
if (mem[mask][aim])return;
mem[mask][aim] = 1;
ans = max(ans, cur);
for (int i = 0; i < n; i++)
{
if (vis[i] == 0 && (gsame[i][aim] || wsame[i][aim]))
{
vis[i] = 1;
dfs(i, cur + 1,mask|(1<<i));
vis[i] = 0;
}
}
}
void solve()
{
memset(vis, 0, sizeof vis);
memset(gsame, 0, sizeof gsame);
memset(wsame, 0, sizeof wsame);
memset(mem, 0, sizeof mem);
ans = 1;
cin >> n;
genres = writers = vector<string>(n);
for (int i = 0; i < n; i++)
{
cin >> genres[i] >> writers[i];
}
//预处理字符串是否相等
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (genres[i] == genres[j])
gsame[i][j] = gsame[j][i] = 1;
if (writers[i] == writers[j])
wsame[i][j] = wsame[j][i] = 1;
}
}
for (int i = 0; i < n; i++)
{
vis[i] = 1;
dfs(i, 1,1<<i);
vis[i] = 0;
}
cout << n - ans << endl;
}