P1171 售货员的难题 货郎担问题 | Uva10817 校长的烦恼

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<" is "<<x<<endl 
using namespace std;
const int N = 25;
const int INF = 0x3f3f3f3f;
int dist[N][N];
int dp[N][1<<21];
int main(){
	int n;
	cin>>n;
	for(int i = 0;i < n;i++)
		for(int j = 0;j < n;j++)
			cin>>dist[i][j];
	for(int i = 0;i < n;i++)
		for(int j = 0; j < (1<<n);j++)
			dp[i][j] = INF;
	for(int i = 0;i < n;i++)dp[i][0] = dist[i][0];
	
	for(int s = 1;s < (1<<n);s++){
		for(int i = 0;i < n;i++){
			if((1<<i)&s)continue;
			for(int j = 0;j < n;j++)
				if((1<<j)&s){
					dp[i][s] = min(dp[i][s],dp[j][s - (1<<j)] + dist[i][j]);
				}					
		}
	}
	cout<<dp[0][(1<<n) - 2]<<endl;
	return 0;
} 

Uva 10817校长的烦恼

这题主要在于压缩状态空间,然后记忆化搜索

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<" is "<<x<<endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define DBG 0
const int N = 125;
typedef long long ll;
const int INF = 1000000000;
const ll LLINF = (1LL<<60);
using namespace std;
const int mod = 998244353;
ll fast_pow(ll a,ll b){
	ll ans = 1;
	while(b){
		if(b&1)ans = (ans * a)%mod;
		a = (a * a)%mod;
		b>>=1;
	}
	return (ans%mod);
}
typedef pair<int,int> pii;
ll s,m,n;
ll c[N],sj[N],dp[N][1<<8][1<<8];
ll solve(int i,int s0,int s1,int s2){
	if(i == m + n){
		return s2 == (1<<s) - 1?0:INF; 
	}
	ll &ans = dp[i][s1][s2];
	if(ans >= 0)
		return ans;
	ans = INF;
	if(i >= m)ans = solve(i + 1,s0,s1,s2);
	int m0 = sj[i] & s0,m1 = sj[i] & s1;
	s0 ^= m0,s1 = (s1 ^ m1)|m0,s2 |= m1;
	ans = min(ans,c[i] + solve(i + 1,s0,s1,s2));
	return ans;
} 
int main(){
	//ios::sync_with_stdio(false);
	//cin.tie(0);
	//cout.tie(0);
#if DBG
	freopen("input.txt","r",stdin);
#endif
	string line;
	while(getline(cin,line)){
		stringstream ss(line);
		ss>>s>>m>>n;
		if(s == 0)break;
		for(int i = 0;i < m + n;i++){
			
			getline(cin,line);
			stringstream ss(line);
			ss>>c[i];
			//debug(c[i]);
			int x;
			sj[i] = 0;
			while(ss>>x)sj[i] |= (1<<(x - 1));
			//debug(sj[i]);
		}
		memset(dp,-1,sizeof(dp));
		cout<<solve(0,(1<<s) - 1,0,0)<<endl;
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值