生活随笔
收集整理的這篇文章主要介紹了
打表+dp思维+博弈
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
E. Sending a Sequence Over the Network
應該屬于一個經(jīng)典dp,可惜我沒做出來。。。
思路:對于一個數(shù)字來說,它可以向左擴展,也可以向有擴展。
設計狀態(tài):f[i]表示第i位數(shù)字能否成功被包括
先討論f[i]是否和法,由狀態(tài)f[i-a[i]-1]轉移得到;只有f[i]被表示時,才可將a[i+1]向右擴展。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std
;
const int N
=2e5+5;
const int inf
=1e18;
const int mod
=998244353;
int n
,a
[N
],f
[N
];void solve()
{cin
>> n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
],f
[i
]=0;f
[0]=1;for(int i
=0;i
<=n
;i
++){if(i
-a
[i
]-1>=0&&f
[i
-a
[i
]-1]) f
[i
]=1;if(!f
[i
]) continue;if(i
+a
[i
+1]+1<=n
&&f
[i
]) f
[i
+a
[i
+1]+1]=1;}if(f
[n
]) cout
<<"YES"<<endl
;elsecout
<<"NO"<<endl
;
}
signed main()
{int T
;cin
>>T
;while(T
--)solve();return 0;
}
C. Chef Monocarp
思路:KM算法求完美匹配的最大權值,左部點和右部點要求個數(shù)相同。
對于本題,左部點為烘培時間,右部點為拿出時間,因為拿出時間的不固定,構建虛點,連線權值要求為0,否則會對答案產生貢獻。
由于是最小權值,轉化為負值,邊初始化為-inf,跑KM算法.
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std
;
const int N
=405;
const int inf
=1e18;
const int mod
=998244353;
int n
,a
[N
];
int w
[N
][N
],lx
[N
],ly
[N
];
bool visx
[N
],visy
[N
];
int match
[N
],delta
,c
[N
],p
[N
];
int A
[N
],P
[N
],B
[N
],C
[N
];
void bfs(int x
)
{int a
,y
=0,y1
=0;for(int i
=1;i
<=n
;i
++) p
[i
]=0,c
[i
]=inf
;match
[y
]=x
;do{a
=match
[y
],delta
=inf
,visy
[y
]=1;for(int b
=1;b
<=n
;b
++){if(!visy
[b
]){if(c
[b
]>lx
[a
]+ly
[b
]-w
[a
][b
])c
[b
]=lx
[a
]+ly
[b
]-w
[a
][b
],p
[b
]=y
;if(c
[b
]<delta
) delta
=c
[b
],y1
=b
;}}for(int b
=0;b
<=n
;b
++)if(visy
[b
]) lx
[match
[b
]]-=delta
,ly
[b
]+=delta
;else c
[b
]-=delta
;y
=y1
;}while(match
[y
]);while(y
)match
[y
]=match
[p
[y
]],y
=p
[y
];
}
int KM()
{for(int i
=1;i
<=n
;i
++) match
[i
]=lx
[i
]=ly
[i
]=0;for(int i
=1;i
<=n
;i
++){for(int i
=0;i
<=n
;i
++) visy
[i
]=0;bfs(i
);}int res
=0;for(int i
=1;i
<=n
;i
++) res
+=w
[match
[i
]][i
];return res
;
}void solve()
{cin
>>n
;for(int i
=1;i
<=2*n
;i
++) a
[i
]=0;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];for(int i
=1;i
<=2*n
;i
++)for(int j
=1;j
<=2*n
;j
++) w
[i
][j
]=-inf
;for(int i
=1;i
<=n
*2;i
++){for(int j
=1;j
<=n
*2;j
++){if(i
<=n
)w
[i
][j
]=(-1)*abs(a
[i
]-j
);else w
[i
][j
]=0;}}n
*=2;cout
<<-KM()<<endl
;
}
signed main()
{ios
;int T
;cin
>>T
;while(T
--)solve();return 0;
}
dp算法:
dp[i][j]表示第i道菜在第j分鐘被拿出所需要的最小花費。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std
;
const int N
=405;
const int inf
=1e18;
const int mod
=998244353;
int n
,a
[N
],dp
[N
][N
];void solve()
{cin
>>n
;for(int i
=1;i
<=n
;i
++) cin
>>a
[i
];sort(a
+1,a
+n
+1);for(int i
=1;i
<=n
;i
++) for(int j
=0;j
<=n
*2;j
++) dp
[i
][j
]=inf
;for(int i
=1;i
<=n
;i
++)for(int j
=1;j
<=n
*2;j
++){dp
[i
][j
]=min(dp
[i
][j
-1],dp
[i
-1][j
-1]+abs(j
-a
[i
]));}int ans
=inf
;for(int i
=1;i
<=2*n
;i
++) ans
=min(dp
[n
][i
],ans
);cout
<<ans
<<endl
;
}
signed main()
{int T
;cin
>>T
;while(T
--)solve();return 0;
}
C. Even Number Addicts
思路:分清必勝態(tài)、必敗態(tài)、先后手影響、各自的最優(yōu)策略。
1.A想讓自己的總和為偶數(shù),偶數(shù)不會影響奇偶性,但奇數(shù)可以。
2.討論奇數(shù)的數(shù)目,及相應偶數(shù)數(shù)量可能會產生的影響。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std
;
const int N
=405;
const int inf
=1e18;
const int mod
=998244353;
int n
,odd
,even
;void solve()
{odd
=even
=0;cin
>>n
;for(int i
=1;i
<=n
;i
++){int x
;cin
>>x
;if(x
%2) odd
++;else even
++;}if(odd
%4==0) cout
<<"Alice"<<endl
;else if(odd
%4==1){if(even
%2) cout
<<"Alice"<<endl
;else cout
<<"Bob"<<endl
;}else if(odd
%4==2) cout
<<"Bob"<<endl
;else if(odd
%4==3){cout
<<"Alice"<<endl
;}}
signed main()
{int T
;cin
>>T
;while(T
--)solve();return 0;
}
I. Invoker
思路:明顯想到要充分利用前一個指令的三個字母,才用dp記錄的方式。
相當于只能儲存3個字母,可打表記錄。
設計狀態(tài):dp[i][j]表示字母i對應命令的第j種排列方式。
初始化:第一個字母固定需要三個命令字符
狀態(tài)轉移:dp[i][j]=min(dp[i][j],dp[i-1][g]+dis(mp[a[s[i-1]]][g],mp[a[s[i]]][j]));
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std
;
const int N
=405;
const int inf
=1e18;
const int mod
=998244353;
int n
,dp
[100005][6];
string s
;
string mp
[10][6]={{"QQQ","QQQ","QQQ","QQQ","QQQ","QQQ"},{"QQW","QWQ","QQW","QWQ","WQQ","WQQ"},{"QQE","QEQ","QQE","QEQ","EQQ","EQQ"},{"WWW","WWW","WWW","WWW","WWW","WWW"},{"QWW","QWW","WQW","WWQ","WQW","WWQ"},{"WWE","WEW","WWE","WEW","EWW","EWW"},{"EEE","EEE","EEE","EEE","EEE","EEE"},{"QEE","QEE","EQE","EEQ","EQE","EEQ"},{"WEE","WEE","EWE","EEW","EWE","EEW"},{"QWE","QEW","WQE","WEQ","EQW","EWQ"}};
map
<char,int>a
;
int dis(string s1
,string s2
)
{if(s1
==s2
) return 0;if(s1
[1]==s2
[0]&&s1
[2]==s2
[1]) return 1;else if(s1
[2]==s2
[0]) return 2;else return 3;
}
void solve()
{a
['Y']=0,a
['V']=1,a
['G']=2,a
['C']=3,a
['X']=4;a
['Z']=5,a
['T']=6,a
['F']=7,a
['D']=8,a
['B']=9;cin
>>s
;n
=s
.length();s
=" "+s
;for(int i
=0;i
<=n
;i
++) for(int j
=0;j
<6;j
++) dp
[i
][j
]=inf
;for(int i
=0;i
<6;i
++) dp
[1][i
]=3;for(int i
=2;i
<=n
;i
++){for(int j
=0;j
<6;j
++){for(int g
=0;g
<6;g
++){dp
[i
][j
]=min(dp
[i
][j
],dp
[i
-1][g
]+dis(mp
[a
[s
[i
-1]]][g
],mp
[a
[s
[i
]]][j
]));}}}int ans
=inf
;for(int i
=0;i
<6;i
++) ans
=min(ans
,dp
[n
][i
]);cout
<<ans
+n
<<endl
;
}
signed main()
{solve();return 0;
}
總結
以上是生活随笔為你收集整理的打表+dp思维+博弈的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。