昨天下午跟队友打的这场比赛,一共出了2题,签到题7分钟出了,但是有个签到题dp我一直被卡,做不出来....然后心态有点无了....幸好队友过了一题。打了三个小时就下班了... 我发现每次比赛我被卡的时候心态都好炸裂啊....我感觉自己在队伍中得尽量不写代码,得队友来写了。不然被题卡住的时候,自己的心态太难调整了...我感觉这次省赛我们队伍应该是获得不了奖了,所以放平心态吧...让自己尽量享受这次经历吧。showmaker说:失败总是贯穿人数始终,这就是人生。我才是第一年,我还有2年的时间,在这两年的时间内,一个人可以改变很多。总之,继续坚持吧。
这题其实就是模拟除法运算,思路还是很好想的,就不多说了...
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n;
int k;
int main(){
scanf("%d%d",&n,&k);
int ans=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
ans=ans+x;
}
printf("%d.",ans/n);
ans=ans%n;
int cnt=1;
while(cnt<=k){
ans=ans*10;
printf("%d",ans/n);
ans=ans%n;
cnt++;
}
return 0;
}
这题我一眼就看出是二维背包的变形问题,但自己真的有个特别坏的毛病,遇见自己感觉做不出来的题目,自己思路就不清晰,开始乱写了...这题我状态表示很好想,但是我状态转移方程都没想明白就开始写了...(我是dp高手?(bushi)),所以一会做dp题目的时候,一定要先想明白状态表示和状态转移方程在写啊!!!还是平常做dp题目的时候,没有这个习惯啊
我们设dp[i][j]为体力为i维他命为j的时候所获得的最多金币数目
当j>h[i]&&k>=s[i]时 (注意k不能等于h[i],因为人的体力不能为0,即我们不能从dp[0][k转移来]) dp[j][k]=max(dp[j][k],dp[j-h[i]][k-s[i]]);
当j>h[i]&&j+k>=h[i]+s[i](此时k-s[i]<0即维他命不足,需要体力来补充,需要补充的为是s[i]-k)
dp[j][k]=max(dp[j][k],dp[j-h[i]-(s[i]-k)][0]);
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n,H,S;
ll h[1005],s[1005],w[1005];
ll dp[305][305];//体力为i,维他命为j的时候的最大金币数目
int main(){
scanf("%d%d%d",&n,&H,&S);
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld",&h[i],&s[i],&w[i]);
}
ll ans=0;
for(int i=1;i<=n;i++){
for(int j=H;j>=h[i];j--){//体力
for(int k=S;k>=0;k--){//维他命
if(j>h[i]&&k>=s[i]){
dp[j][k]=max(dp[j][k],dp[j-h[i]][k-s[i]]+w[i]);
}else{
if(j>h[i]&&j+k>h[i]+s[i]){
int res=s[i]-k;
dp[j][k]=max(dp[j][k],dp[j-h[i]-res][0]+w[i]);
}
}
ans=max(ans,dp[j][k]);
}
}
}
printf("%lld\n",ans);
return 0;
}
以后写dp题目一定要先想明白状态表示和状态转移方程在下笔啊!!!!不要再瞎写了啊!!!
英文题面是真的恶心啊,比赛的时候题面都读不懂啊.....
这题题目都没读懂,直接开翻译;
比赛时候没做出来,我们都感觉是搜索之类的...其实就是个思维+构造
注意:题目中第1行第n行和第1列第m列都为0;
所以我们可以让A的第一行为1,B的第n行为m,然后让A的奇数列为1(除了第n行),让B的偶数列为1(除了第一行),因为我们要使AB中原来为0的地方至少有一个为0(这里行列是等效的)
一开始我是这样想的A的所有奇数行为1,B的所有偶数行为1,这样为啥不行啊?...
比如:
000000
1111111
000000
1111111
000010
上面的例子虽然所有的偶数行为1,但是所有的1都不连通,所有AB都需要一列来联通
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int n,m;
int a[505][505];
int b[505][505];
string c[505];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
cin>>c[i];
}
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
if(c[i][j]=='1'){
a[i][j+1]=1;
b[i][j+1]=1;
}
}
}
for(int i=1;i<=m;i++){
a[1][i]=1;
b[n][i]=1;
}
for(int i=1;i<=m;i=i+2){
for(int j=1;j<n;j++){
a[j][i]=1;
}
}
for(int i=2;i<=m;i=i+2){
for(int j=2;j<=n;j++){
b[j][i]=1;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d",a[i][j]);
}
printf("\n");
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
printf("%d",b[i][j]);
}
printf("\n");
}
return 0;
}
这题题目是真的恶心,好多看不懂的单词还有好多没用的单词...
最后还是开了翻译,幸好队友做了出来了...
一开始我发现前几个样例,发现边数为2n+2,然后又发现了一个样例不符合;然后我感觉是前缀和...其实不是...
n个方块单独放时候的边数为4n,所以我们只需要减去重叠的时候边的数目即可;
我们考虑重力为竖直向下的时候,如果一个方块下面有一个方块,ans需要减去2,如果这个方块左边有相邻的方块ans也需要减2,右边也同理(画个图还是很好想的)
想到这代码应该就很好写了
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
using namespace std;
typedef long long ll ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if (ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
void print(__int128 num) {
if(num) {
print(num/10);
putchar(num%10+'0');
}
}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(b==0){
x=1;
y=0;
return a;
}
ll d=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return d;
}
int vis1[200005];//行
int vis2[200005];//列
int n;
int main(){
scanf("%d",&n);
int ans1=0;
int ans2=0;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
vis1[x]++;
vis2[y]++;
ans1=ans1+4;//向下
ans2=ans2+4;//向左
if(vis2[y]>1){
ans1=ans1-2;
}
if(vis2[y-1]>=vis2[y]){
ans1=ans1-2;
}
if(vis2[y+1]>=vis2[y]){
ans1=ans1-2;
}
if(vis1[x]>1){
ans2=ans2-2;
}
if(vis1[x-1]>=vis1[x]){
ans2=ans2-2;
}
if(vis1[x+1]>=vis1[x]){
ans2=ans2-2;
}
printf("%d %d\n",ans1,ans2);
}
return 0;
}